Фильтровать массив объектов путем сравнения их свойств - PullRequest
0 голосов
/ 11 ноября 2018

Я пытался найти наивысшую оценку объекта в этом массиве, но результат неверный. Должны ли мы сбросить счет на 0 снова? Я пытался поместить переменную оценки ниже obj[i.class], но ничего не изменилось:

function theScore (students) {
  var obj = {};
  score = 0;
  for(i of students){
    if(score < i.score) {
      obj[i.class] = {
        name: i.name,
        score: i.score
      };
    };
  };
  return obj;
};


console.log(theScore([
  {
    name: 'Sara',
    score: 90,
    class: 'A'
  },
  {
    name: 'Poyi',
    score: 85,
    class: 'B'
  },
  {
    name: 'Adert',
    score: 74,
    class: 'A'
  },
  {
    name: 'Shynta',
    score: 78,
    class: 'B'
  }
]));

Желаемый вывод:

{
A: { 
        name: 'Sara',
        score: 90
   },
B: {
        name: 'Poyi',
        score: 85
   }
}

Ответы [ 5 ]

0 голосов
/ 11 ноября 2018

Проблема с вашим кодом никогда не заключалась в сравнении фактической оценки объекта, а всегда в 0.

Если вы действительно хотите использовать цикл for in для этого, вы можете сделать что-то вроде (с небольшими изменениями в вашем коде):

var data = [ { name: 'Sara', score: 90, class: 'A' }, { name: 'Poyi', score: 85, class: 'B' }, { name: 'Adert', score: 74, class: 'A' }, { name: 'Shynta', score: 78, class: 'B' } ]

function theScore (students) {
  var obj = {}
  for(i of students){
    if(!obj[i.class] || obj[i.class].score < i.score) {
      obj[i.class] = {name: i.name, score: i.score}
    }
  }
  return obj
}

console.log(theScore(data))

Или вы можете использовать reduce и решить это так:

var data = [ { name: 'Sara', score: 90, class: 'A' }, { name: 'Poyi', score: 85, class: 'B' }, { name: 'Adert', score: 74, class: 'A' }, { name: 'Shynta', score: 78, class: 'B' } ]

const maxByClass = (d) => d.reduce((r,{name, score, ...c}) => {
  r[c.class] = r[c.class] ? r[c.class].score > score ? r[c.class] : {name, score} : {name, score}
  return r
}, {})

console.log(maxByClass(data))

Так как Reduce возвращает аккумулятор, нам просто нужно назначить правильный объект, основанный на том, какой из двух классов баллов больше, и вернуть.

0 голосов
/ 11 ноября 2018

Вам необходимо отследить уже проверенный classes.

Более чистая альтернатива - использовать функцию Array.prototype.reduce для получения желаемого результата. Как вы можете видеть, в основном, этот подход отслеживает ранее проверенный classes.

function theScore (students) {
  return students.reduce((a, c) => { 
    a[c.class] = (a[c.class] || (a[c.class] = c));
    if (c.score > a[c.class].score) a[c.class] = c;
    return a;
  }, Object.create(null));
}


console.log(theScore([  {    name: 'Sara',    score: 90,    class: 'A'  },  {    name: 'Poyi',    score: 85,    class: 'B'  },  {    name: 'Adert',    score: 74,    class: 'A'  },  {    name: 'Shynta',    score: 78,    class: 'B'  }]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 11 ноября 2018

Разве вы не можете существенно упростить назначение функций вашей функции?

function theScore (students) {
    var obj = {};
    var score = 0;
    for(i of students){
        if(i.score > score ) { 
            score = i.score;     // Keep track of the highest-score-found-so-far
            obj = i;             // Keep track of the highest scoring object
        }
    }
    return obj;
}
0 голосов
/ 11 ноября 2018

Проблема с вашим кодом состоит в том, что вы не проводите никаких различий между оценками учащихся в одном классе и в другом. Вы также не обновляете оценку, когда находите более высокую оценку, поэтому оценка каждого учащегося (если она не равна 0) будет выше, чем score каждый раз, когда выполняется цикл, и вы просто в итоге получаете последнюю оценку в списке.

РЕДАКТИРОВАТЬ: отредактировано, чтобы показать, как сделать это только с одним циклом

Вам необходимо:

  1. Трек для каждого класса
  2. Цикл над учениками
  3. Сравните оценку этого студента с высокой оценкой класса для класса этого студента
  4. Обновлять по мере необходимости
  5. Повторяйте, пока не закончите.

function theScore (students) {
  const highScoresByClass = {};
  const scores = {A: 0, B: 0, C: 0};
  for (const student of students){
    const classHighScore = scores[student.class];
    if(classHighScore < student.score) {
      scores[student.class] = student.score;
      highScoresByClass[student.class] = {
        name: student.name,
        score: student.score
      };
    };
  };
  return highScoresByClass;
};


console.log(theScore([
  {
    name: 'Sara',
    score: 90,
    class: 'A'
  },
  {
    name: 'Poyi',
    score: 85,
    class: 'B'
  },
  {
    name: 'Adert',
    score: 74,
    class: 'A'
  },
  {
    name: 'Shynta',
    score: 78,
    class: 'B'
  }
]));
0 голосов
/ 11 ноября 2018

Счет не изменяется после того, как вы найдете самый высокий балл. Измените счет на текущий счет. Благодарю. Вместо объекта с картой используйте объект с индексом (массив). Это должно работать.

function theScore (students) {
  var obj = [];
  score = 0;
  for(i of students){
    if(obj.length === 0) {
       obj.push( i );
    } else {
      for( var x = 0; x < obj.length; x++ ){
         if( i.score > obj[x].score ){
             obj.splice( x, 0, i );
             break;
         }
      }
      if( x === obj.length ){
        obj.push(i);
      }
    }
  };
  return obj;
};


console.log(theScore([
  {
    name: 'Sara',
    score: 90,
    class: 'A'
  },
  {
    name: 'Poyi',
    score: 85,
    class: 'B'
  },
  {
    name: 'Adert',
    score: 74,
    class: 'A'
  },
  {
    name: 'Shynta',
    score: 78,
    class: 'B'
  }
]));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...