Javascript, использующий if else для определения значения массива

Я пытаюсь несколько раз получить 2 ввода и сохранить их в массиве, пока не наберется слово «конец», после чего я хочу дать оценку за каждую из введенных меток. Однако независимо от того, какие оценки были введены, я получал «HD» для всех оценок.

Любой совет приветствуется! Благодарность!

const readline = require('readline-sync');

var name, marks;
var studentList = [];

Input();

function printList(list) {
  for (let i = 0; i < studentList.length; i += 1) {
    var grade;
      if ((marks <= 100) && (marks => 80)){
          grade = 'HD'
          studentList[i][2] = grade;  

        } 
        else if ((marks <= 79) && (marks => 70)) 
        {
            grade = 'D'
            studentList[i][2] = grade;

        } 
        else if ((marks <= 69) && (marks =>60)) 
        {
            grade = 'C'
            studentList[i][2] = grade;

        } 
        else if ((marks <= 59) && (marks =>51)) 
        {
            grade = 'P'
            studentList[i][2] = grade;

        } 
        else if ((marks < 50) && (marks =>0)) 
        {
            grade = 'N'
            studentList[i][2] = grade;

        }
        console.log(studentList[i]);
    }       

}

function Input()
{
  while(true) {
    console.log("Please enter the student name (or "end" to end): ");
    name = readline.question("Student Name: ");
    if (name === 'end') {
      printList(studentList)
      break
    }
    console.log("Student Name is" , name);
    marks = readline.question("Enter marks for " + name + ": ");
    if (marks === 'end') {
      printList(studentList)
      break
    }
    console.log("Marks for " + name + " is " + marks );
    studentList.push([name, marks]);
  }
}

Всего 2 ответа


Вы используете функцию со стрелкой, и это всегда true (если обернуто).

marks => 80

var marks = 1; // assuming a number

if ((marks <= 100) && (marks => 80)) {
    console.log('true');
}

Вместо этого возьмите правильный знак сравнения >=

var marks = 1; // assuming a number

if (marks <= 100 && marks >= 80) { // no extra parentheses required
    console.log('true');
} else {
    console.log('false');
}


Помимо функции со стрелкой, на которую указывает Нина (как я это пропустил ?!) :

Вы сравниваете строки, а не числа. Когда вы сравниваете строки, содержащие цифры, результаты не совпадают с результатами сравнения чисел.

При составлении списка учеников и оценок конвертируйте marks в числа. Например:

studentList.push([name, parseFloat(marks)]);

parseFloat - только один из ваших вариантов, см. мой ответ здесь для краткого изложения различных способов преобразования строк в числа.


Несколько замечаний по вашей структуре if / else if :

  • Это не относится к случаю, когда marks > 100 .

  • Если вы делаете их в порядке убывания, вам не нужно перечислять нижнюю границу

  • Нет необходимости присваивать studentList[i][2] друг другу, else if блок; просто сделай это один раз в конце

Например:

if (marks > 100 || marks < 0)
{
    throw new Error("Invalid 'marks' value");
}
else if (marks >= 80)
{
    grade = 'HD'
} 
else if (marks >= 70) 
{
    grade = 'D'
} 
else if (marks >= 60) 
{
    grade = 'C'
} 
else if (marks >= 51) 
{
    grade = 'P'
} 
else // No `if (marks >= 0)` because we know it is, otherwise we would have throw an error above
{
    grade = 'N'
}
studentList[i][2] = grade;

Есть несколько других проблем:

  1. Вы повторно используете последние введенные marks а не используете marks для конкретного учащегося в цикле. Вам нужно добавить

    var marks = list[i][1];
    

    внутри вашего цикла, чуть выше if / else if выше.

  2. Ваша функция Input должна называться input (это не функция конструктора, поэтому она не должна быть написана заглавными буквами).

  3. Нет имени причины, marks , а studentList должен быть глобальным. Они должны быть локальными переменными в вашей input функции. А создание printList выявило бы проблему marks с printList , потому что вы пытались бы использовать значение неопределенного идентификатора ( marks ).

  4. (Почти) Весь новый код должен быть написан в строгом режиме , либо путем написания его внутри модуля JavaScript, либо с помощью "use strict"; в верхней части сценария.

  5. Я бы не использовал массив для записей в studentList , я бы использовал объект с именованными свойствами, чтобы вам не приходилось иметь магические числа 1 и 2 в list[i][1] и list[i][2] в printList .

  6. Это совершенно необязательно, но вы можете использовать цикл for, а не цикл for для обхода массива.

  7. Размещение фигурных скобок ( {} ), использование точки с запятой и выбор кавычек ( " против ' ) в вашем коде не согласованы. Я настоятельно рекомендую быть последовательными (я также рекомендую писать точки с запятой явно, а не полагаться на автоматическую вставку точек с запятой [ASI) ], но есть большое меньшинство, которое целенаправленно полагается на ASI. Точно так же, похоже, в настоящий момент все ярость использовать ' вместо " , который я считаю орехами [я использую " или литералы шаблона), но это определенно мнение большинства .)

  8. Поскольку вы использовали let в одном месте, я так понимаю, вы не обязаны использовать ES5 и более ранние версии. В таком случае я рекомендую никогда не использовать var .

  9. Действительно незначительный, но «отметки» неверны; это должно быть «пометить» или «пометить». В этом коде это всего лишь одна отметка, поэтому mark будет иметь больше смысла, но в приведенной ниже версии я оставил ее в виде marks на тот случай, если это указано в вашем назначении для его вызова.

Объединение всех этих комментариев и использование очень распространенного стиля связывания (вариант стиля Керниган и Ричи, часто [и раздражающе] называемый «единый истинный стиль скобок»):

"use strict";
const readline = require('readline-sync');

input();

function printList(list) {
    for (const entry of list) {
        // Get a local for `marks` via destructuring
        const {marks} = entry;
        if (marks > 100 || marks < 0) {
            throw new Error(`Invalid 'marks' value: ${marks}`);
        } else if (marks >= 80) {
            entry.grade = 'HD'
        } else if (marks >= 70) {
            entry.grade = 'D'
        } else if (marks >= 60) {
            entry.grade = 'C'
        } else if (marks >= 51) {
            entry.grade = 'P'
        } else { // No `if (marks >= 0)` because we know it is, otherwise we would have thrown an error above
            entry.grade = 'N'
        }
        console.log(entry);
    }       
}

function input() {
    const studentList = [];
    while (true) {
        console.log('Please enter the student name (or "end" to end): ');
        const name = readline.question('Student Name: ');
        if (name === 'end') {
            printList(studentList);
            break;
        }
        console.log('Student Name is' , name);
        const marks = readline.question('Enter marks for ' + name + ': ');
        if (marks === 'end') {
            printList(studentList);
            break;
        }
        console.log('Marks for ' + name + ' are ' + marks );
        studentList.push({name, marks: parseFloat(marks)});
    }
}

Использование стиля связывания, который вы в основном использовали в своем коде, который обычно называется стилем Allman или BSD:

"use strict";
const readline = require('readline-sync');

input();

function printList(list)
{
    for (const entry of list)
    {
        // Get a local for `marks` via destructuring
        const {marks} = entry;
        if (marks > 100 || marks < 0)
        {
            throw new Error(`Invalid 'marks' value: ${marks}`);
        }
        else if (marks >= 80)
        {
            entry.grade = 'HD'
        }
        else if (marks >= 70)
        {
            entry.grade = 'D'
        }
        else if (marks >= 60)
        {
            entry.grade = 'C'
        }
        else if (marks >= 51)
        {
            entry.grade = 'P'
        }
        else // No `if (marks >= 0)` because we know it is, otherwise we would have thrown an error above
        {
            entry.grade = 'N'
        }
        console.log(entry);
    }       
}

function input() {
    const studentList = [];
    while (true)
    {
        console.log('Please enter the student name (or "end" to end): ');
        const name = readline.question('Student Name: ');
        if (name === 'end')
        {
            printList(studentList);
            break;
        }
        console.log('Student Name is' , name);
        const marks = readline.question('Enter marks for ' + name + ': ');
        if (marks === 'end')
        {
            printList(studentList);
            break;
        }
        console.log('Marks for ' + name + ' are ' + marks );
        studentList.push({name, marks: parseFloat(marks)});
    }
}

Я с радостью использовал этот бодрящий стиль (в C, C ++, Java, C #, а затем в JavaScript) около 20 лет, но просто знайте, что в кругах JavaScript он встречается редко (и по этой причине я его больше не использую), возможно, частично из-за того, что с ним связан лабиринт ASI и ключевое слово return : если вы хотите вернуть объект, созданный с помощью литерала, у вас может возникнуть соблазн сделать это:

// DON'T DO THIS
return
{
    foo: "bar"
};

Это вернет undefined , потому что правила ASI говорят, что движок JavaScript должен вставлять точку с запятой после этого return , обрабатывая его так:

// Blech
return;
{
    foo: "bar"
};

Этого, конечно, легко избежать, и это скорее недостаток в ASI, чем в стиле Allman, но, опять же, модифицированный стиль K & R гораздо чаще встречается в кругах JavaScript, чем стиль Allman.


Есть идеи?

10000