Учитывая следующий массив json
const groups=[{ id:1, parent:null, groupName:'Others', maxScore:3},
{id:2, parent:null, groupName: 'Group 1', maxScore:0},
{id:3, parent:2, groupName:'Others, maxScore:2},
{id:4, parent:2, groupName:'Sub Group 1', maxScore:1}];
Какой подход к суммированию maxScores в пределах родители был бы более ориентированным на производительность? Это похоже на древовидную структуру, но узлы не имеют ссылок на своих дочерних элементов.
Я пробую подход map.reduce прямо сейчас
function addMaxScoreToGroups(groups) {
return groups.map((group) => {
const newGroup = group;
if (group.parent === null && group.name !== 'Others') {
const children = groups.filter(elem => elem.parent === group.id);
if (children) {
newGroup.maxScore = children.map(x => x.maxScore)
.reduce((value, acum) => value + acum);
}
}
return newGroup;
});
}
Ожидаемый результат будет
const groups=[{ id:1, parent:null, groupName:'Others', maxScore:3},
{id:2, parent:null, groupName: 'Group 1', maxScore:0,maxPosibleScore:3},
{id:3, parent:2, groupName:'Others, maxScore:2},
{id:4, parent:2, groupName:'Sub Group 1', maxScore:1}];
На самом деле он работает, но я думаю, что его можно оптимизировать с точки зрения того, сколько раз мне нужно использовать map.reduce, чтобы получить правильный результат.
Если ваш код работает, и вы ищете оптимизацию, codereview.stackexchange.com может дать вам лучшие ответы, поскольку такие вопросы обычно не по теме в Stackoverflow. Посмотрите, какие вопросы По теме и какие Не по теме



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Итерируйте с помощью Array.reduce(). Для каждого объекта создайте новую запись (или обновите существующую в случае родительского) путем клонирования объекта с помощью распространение объекта (или Object.assign().
Если у объекта есть родительский объект, создайте его, если он не существует, и добавьте / обновите maxPossibleScore.
Преобразуйте обратно в массив с помощью Object.values().
const groups=[{ id:1, parent:null, groupName:'Others', maxScore:3}, {id:3, parent:2, groupName:'Others', maxScore:2}, {id:4, parent:2, groupName:'Sub Group 1', maxScore:1}, {id:2, parent:null, groupName: 'Group 1', maxScore:5}];
const ms = 'maxScore';
const mps = 'maxPossibleScore';
const result = Object.values(groups.reduce((r, o) => {
// clone
const c = { ...o };
// if current parent initalized before, update maxPossibleScore
if (!o.parent && r[o.id]) c[mps] = r[o.id][mps] + c[ms];
r[o.id] = c;
if (o.parent) {
// if parent doesn't exist init
r[o.parent] = r[o.parent] || {};
// if parent.maxPossibleScore doesn't exist init it
if (!(mps in r[o.parent])) {
r[o.parent][mps] = r[o.parent][ms] || 0;
}
r[o.parent][mps] += o[ms];
}
return r;
}, {}));
console.info(result);Наверное @nope :)
Почему? OP запросил более эффективный код, почему ваш код будет работать лучше, чем существующий код OP, и как вы это определяете? jsPerf или аналогичный?
Обозначение Big O - O (n) против как минимум O (n ^ 2) (текущее решение). Поскольку мы используем reduce, которое вызывает функции обратного вызова, он менее эффективен, чем простой цикл for.
@OriDrori, это не работает :( Если у меня только один родитель = null, его maxPosibleScore остается 0
Должен быть исправлен сейчас. Если нет, добавьте тестовый пример в комментарии.
Вопросы, касающиеся Самый лучший...., очень субъективны. То, что выполняет Лучший для одного, может не работать для другого. Вы можете использовать jsPerf или аналогичные сайты / инструменты для тестирования производительности подходов / решений, которые работают / дают правильные результаты, и использовать то, что лучше всего соответствует вашему сценарию. - Если у вас еще нет рабочего решения, перефразируйте вопрос, чтобы сосредоточиться на нем.