javascript массив объектов — перераспределение

#javascript #arrays

#javascript #массивы

Вопрос:

 const current = [
{ studentName: 'Name', ItemNumber: 1, Score: 0 }, 
{ studentName: 'Name', ItemNumber: 2, Score: 1 }]

const needed = [
{ studentName: 'Name', Item1Score: 0, Item2Score: 1 }
]

const names = [...new Set(current.map(v=>v.studentName))]
const items = [...new Set(current.map(v=>v.ItemNumber))].length

 

Как я могу преобразовать текущий массив в тот, который мне нужен? Я знаю, как получить отдельные имена учащихся и количество элементов, но я не знаю, как эффективно объединить эту информацию, чтобы получить необходимый массив.

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

1. Что вы пытаетесь сделать?

2. в конечном итоге я буду использовать новый массив (требуется константа) как часть таблицы данных: material-ui.com/components/data-grid

Ответ №1:

Сначала вы захотите собрать всех учащихся по имени, а затем начать комбинировать свойства на основе этого ItemNumber

 const current = [
{ studentName: 'Name', ItemNumber: 1, Score: 0 }, 
{ studentName: 'Name', ItemNumber: 2, Score: 1 }]

const map = current.reduce((map, { studentName, ItemNumber, ...props }) => {
  // collect by studentName
  return map.set(studentName, {
    ...(map.get(studentName) ?? {}), // merge any previously found entries
    ...Object.fromEntries(Object.entries(props).map(([ key, val ]) =>
      [ `Item${ItemNumber}${key}`, val ]))
  })
}, new Map())

const needed = Array.from(map, ([ studentName, data ]) => ({
  studentName,
  ...data
}))

console.info(needed) 

Это принимает любое свойство, которое не studentName является or ItemNumber , и добавляет к нему префикс «Item<ItemNumber>», поэтому, если у вас есть другие свойства Score , это также будет работать для них.

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

1. это отличный ответ, поскольку он выходит за рамки требований. Теперь я могу получить доступ ко всем значениям, связанным с учеником, а не только к баллам по пунктам 1 и 2.

2. один дополнительный вопрос: как бы вы отредактировали ответ, чтобы разрешить агрегирование всех баллов для каждого учащегося, чтобы необходимый массив теперь выглядел следующим образом: const needed = [ { studentName: ‘Name’, totalScore: 1, Item1Score: 0, Item2Score: 1 } ]

Ответ №2:

Используется Array.reduce() для создания объекта словаря из обоих наборов оценок, на которые ссылается имя учащегося. Затем преобразуйте объект словаря в массив объектов в запрошенном формате, используя комбинацию Object.entries() и Array.map() .

 const current = [
{ studentName: 'Name', ItemNumber: 1, Score: 0 }, 
{ studentName: 'Name', ItemNumber: 2, Score: 1 }];

const neededDict = current.reduce((acc, {studentName, ItemNumber, Score})=>{
        acc[studentName][`item${ItemNumber}Score`] = Score;
    }), {});

const needed = Object.entries(neededDict).map(([key, value])=>{
    return {
        studentName: key,
        Item1Score: value.Item1Score,
        Item2Score: value.Item2Score
    };
}
console.log(needed);