Функция Javascript, возвращающая ‘undefined’

#javascript #arrays #data-structures #nested-lists #undefined-function

#javascript #массивы #структуры данных #вложенные списки #неопределенная-функция

Вопрос:

Я написал функцию, которая принимает оценку в качестве параметра и должна возвращать буквенную оценку. При написании кода необходимо соблюдать некоторые условия. ie: return 'A' if 25 < score <= 30 return 'B' if 20 < score <= 25 и так далее. Поэтому я хотел сделать это, опустив множество if-else's . Поскольку я новичок в javascript, это все, что я мог придумать:

 // This function takes Nested arrays and a single number, 
// which checks its availability in 
// the inside array and then return the index of the array
function my_index(arr, score) {
    for (const [index, elem] of arr.entries()) {
        if (elem.includes(score)) {
            return index;
        }
        
    }
}

// function to get letter grade
function getGrade(score) {
    let grade;
    var gradeDict = {
        'A': [26, 27, 28, 29, 30],
        'B': [21, 22, 23, 24, 25],
        'C': [16, 17, 18, 19, 20],
        'D': [11, 12, 13, 14, 15],
        'E': [6, 7, 8, 9, 10],
        'F': [0, 1, 2, 3, 4, 5] 
    }
    var keys = Object.keys(gradeDict);
    var values = [Object.values(gradeDict)]
    grade = keys[my_index(values, score)]
        
    return grade;
}
 

Первая функция работает нормально. Возвращает индекс вложенного массива. Но основная функция getGrade возвращается 'Undefined' . Не могу придумать лучшего решения, чем это, чтобы уменьшить кучу уродливых if-else.

 var question = {
    '1st': 'Can anybody help me get this done?',
    '2nd': 'Is there any better way to do this?'
}
 

Комментарии:

1. Попробуйте value = Object.values(gradeDict) , а не value = [Object.values(gradeDict)] . Первый создает массив like [[[26, 27 28, 29, 30], ...]] , второй — массив lke [[26, 27, 28, 29, 30], ...] , что больше соответствует my_index ожиданиям.

2. Поскольку я разработал ‘my_index’ для вложенного списка, я подумал, что должен сделать его списком списка в ‘getGrade’. Теперь это работает, большое вам спасибо. И есть ли лучший способ добиться этого, кроме этого?

3. Любое решение, имеющее [26, 27, 28, 29, 30] etc., не является хорошим решением, имхо. Это диапазоны последовательных целых чисел, поэтому нет необходимости хранить их в виде списков. Один из способов понять, что это плохое решение, — увеличить размер проблемы — допустим, существует 26 классов (от А доЯ) или 1 миллион классов. Как бы в этом случае выглядело ваше решение с использованием списков? Это ваш ключ к пониманию того, что решение на основе списков — плохой выбор.

4. Спасибо, что указали на это. Не могли бы вы показать лучшее решение? @jarmod

5. ceil Решение лучше, имо. Это намного проще и является лучшим обобщением.

Ответ №1:

Есть ли лучший способ написать это?

Я бы сделал:

 function getLetterGrade(score) {
  return ['F', 'F', 'E', 'D', 'C', 'B', 'A'][Math.ceil(score / 5)];
}
 

( F встречается дважды, потому что больше баллов сопоставляется с F, чем с другими оценками)

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

Комментарии:

1. в нашей текущей ситуации оценка за каждую оценку соответствует 5 числам, за исключением ‘F’. таким образом, мы можем разделить счет на 5. Но если наши оценки для каждой оценки не совпадают, т.Е.: 5, 6 и так далее. каким будет ваше решение в подходе Math.ceil? @meriton

Ответ №2:

Удалите внешний [] массив Object.values . Object.values уже возвращает значения в array .

От

 var values = [Object.values(gradeDict)];
 

Для

 var values = Object.values(gradeDict);
 

рабочий пример:

 function my_index(arr, score) {
  for (const [index, elem] of arr.entries()) {
    if (elem.includes(score)) {
      return index;
    }
  }
}

function getGrade(score) {
  let grade;
  var gradeDict = {
    A: [26, 27, 28, 29, 30],
    B: [21, 22, 23, 24, 25],
    C: [16, 17, 18, 19, 20],
    D: [11, 12, 13, 14, 15],
    E: [6, 7, 8, 9, 10],
    F: [0, 1, 2, 3, 4, 5],
  };
  var keys = Object.keys(gradeDict);
  var values = Object.values(gradeDict);
  grade = keys[my_index(values, score)];

  return grade;
}

console.log(getGrade(5));
console.log(getGrade(25)); 

Альтернативное решение

 function getGrade(score) {
  let grade;
  var gradeDict = {
    A: [26, 27, 28, 29, 30],
    B: [21, 22, 23, 24, 25],
    C: [16, 17, 18, 19, 20],
    D: [11, 12, 13, 14, 15],
    E: [6, 7, 8, 9, 10],
    F: [0, 1, 2, 3, 4, 5],
  };

  for (let key in gradeDict) {
    if (gradeDict[key].includes(score)) return key;
  }

  return "Not found";
}

console.log(getGrade(5));
console.log(getGrade(25)); 

Комментарии:

1. Спасибо, чувак, как предложил @meriton. Это работает таким образом

2. @ImtiazAhmed включено альтернативное решение

3. Вы также можете искать элемент в массиве, используя find , filter также.

4. Спасибо, чувак! Я ценю это. Решение, исключающее метод my_index, является потрясающим.

Ответ №3:

Мне нравится ceil решение, предложенное ранее, но вот еще одно общее решение на случай, если оно окажется полезным:

 function grade(score) {
  if (score < 0 || score > 30) throw RangeError(`Score ${score} out of range`);

  for (let ii = 5; ii >= 0; ii--) {
    if (score > 5*ii) return String.fromCharCode(70 - ii);
  }

  return 'F';
}

console.log(0, '=>', grade(0))   // F
console.log(4, '=>', grade(4))   // F
console.log(6, '=>', grade(6))   // E
console.log(10, '=>', grade(10)) // E
console.log(27, '=>', grade(27)) // A
console.log(30, '=>', grade(30)) // A
 

Комментарии:

1. При попытке другого подхода я на самом деле боролся с условием ‘0> оценка> 30’