Как наиболее эффективно агрегировать массив объектов по идентификатору?

#javascript #node.js #algorithm

#javascript #node.js #алгоритм

Вопрос:

Мой начальный набор данных представляет собой массив объектов, содержащих метрики, каждый из которых содержит идентификатор. Мне нужно преобразовать этот набор данных в массив агрегатов по идентификатору. Например:

 const startingArray = [
  { id: 1, metricA: 5, metricB: 8, metricC: 1 }
  { id: 2, metricA: 4, metricB: 0, metricC: 7 }
  { id: 1, metricA: 9, metricB: 8, metricC: 2 }
  { id: 3, metricA: 1, metricB: 8, metricC: 2 }
  { id: 3, metricA: 6, metricB: 6, metricC: 1 }
  { id: 2, metricA: 3, metricB: 1, metricC: 9 }
  { id: 1, metricA: 3, metricB: 9, metricC: 8 }
]

const aggregates = {};

startingArray.forEach((item) => {
  if (!aggregates[item.id]) {
    aggregates[item.id] = {
      id: item.id,
      metricA: item.metricA, 
      metricB: item.metricB, 
      metricC: item.metricC
    }
  } else {
    aggregates[item.id].metricA  = item.metricA,
    aggregates[item.id].metricB  = item.metricB,
    aggregates[item.id].metricC  = item.metricC
  }
});

// convert to flat array using lodash toArray() method
const endingArray = toArray(aggregates);

// results:
// [
//   { id: 1, metricA: 17, metricB: 25, metricC: 11 }
//   { id: 2, metricA: 5, metricB: 1, metricC: 16 }
//   { id: 3, metricA: 5, metricB: 8, metricC: 3 }
// ]
 

Массивы могут быть массивными, каков наиболее эффективный способ обработки этого набора данных?

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

1. в endingArray id:2 имеет вводящее в заблуждение значение для metricB оно должно быть 1 или, возможно, startingArray имеет неправильное значение ……. пожалуйста, проверьте значение и поделитесь своим кодом, в котором у вас возникли проблемы.

2. Вы правы, я обновил вопрос правильными значениями.

Ответ №1:

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

 const
    data = [{ id: 1, metricA: 5, metricB: 8, metricC: 1 }, { id: 2, metricA: 4, metricB: 0, metricC: 7 }, { id: 1, metricA: 9, metricB: 8, metricC: 2 }, { id: 3, metricA: 1, metricB: 8, metricC: 2 }, { id: 3, metricA: 6, metricB: 6, metricC: 1 }, { id: 2, metricA: 3, metricB: 1, metricC: 9 }, { id: 1, metricA: 3, metricB: 9, metricC: 8 }],
    result = Object.values(data.reduce((r, { id, ...o }) => {
        Object.entries(o).forEach(([k, v]) => {
            r[id] ??= { id };
            r[id][k] = (r[id][k] || 0)   v;
        });
        return r;
    }, {}));

console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; }