I need to convert an array of objects into a new array with objects including a new type field
percent
. The task is this - each object in the array has a defaultWeight
field with a numeric value. In this array, I have to add the defaultWeight
of the current array to the sum of sumArray
, then I take the defaultWeight
value, divide by sumArray
and multiply by 100 (defaultWeight / sumArray * 100)
. Thus, I get the percentage of the number that I have to put in the new percent
field, which depth of these arrays would not be encountered in the future. Help me, I've been racking my head for the second day. Below is an example:
[
{
"id": 1,
"name": "Блок «Тест1»",
"weight": null,
"defaultWeight": 0.3,
"children": [
{
"id": 1,
"name": "Планирование активностей",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 2,
"name": "Выполнение плана по визитам",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 3,
"name": "Выполнение плана по групповым мероприятиям",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 4,
"name": "Выполнение маркетинговой стратегии (включает три KPI)",
"weight": null,
"defaultWeight": 1,
"children": [
{
"id": 5,
"name": "Охват базы",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 6,
"name": "Соблюдение кратности посещения специалистов",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 7,
"name": "Интервальность",
"weight": null,
"defaultWeight": 1,
"children": []
}
],
"children": [
{
"id": 5,
"name": "Охват базы",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 6,
"name": "Соблюдение кратности посещения специалистов",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 7,
"name": "Интервальность",
"weight": null,
"defaultWeight": 1,
"children": []
}
]
},
{
"id": 14,
"name": "Время, проведённое на визитах в день",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 15,
"name": "Средняя длительность визита",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 16,
"name": "Доля рабочего дня на активности",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 17,
"name": "Геолокация",
"weight": null,
"defaultWeight": 1,
"children": []
}
]
},
{
"id": 2,
"name": "Блок «Тест2»",
"weight": null,
"defaultWeight": 0.2,
"children": [
{
"id": 8,
"name": "% выполнения «Двойной визит» (оценка РМа)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 9,
"name": "% выполнения «Аудит» (оценка РМа)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 10,
"name": "% выполнения «Двойной визит» (оценка Аудитора)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 11,
"name": "% выполнения «Аудит» (оценка Аудитора)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 19,
"name": "Средневзвешенное с весами оценки РМа и Аудитора",
"weight": null,
"defaultWeight": 1,
"children": []
}
]
},
{
"id": 3,
"name": "Блок «Тест3»",
"weight": null,
"defaultWeight": 0.5,
"children": [
{
"id": 26,
"name": "Выполнение плана продаж",
"weight": null,
"defaultWeight": 0.9,
"children": []
},
{
"id": 27,
"name": "Темп прироста",
"weight": null,
"defaultWeight": 0.025,
"children": []
},
{
"id": 28,
"name": "Evolution Index",
"weight": null,
"defaultWeight": 0.025,
"children": []
},
{
"id": 29,
"name": "Динамика фактической доли на рынке",
"weight": null,
"defaultWeight": 0.025,
"children": []
},
{
"id": 30,
"name": "Сравнение фактической доли на рынке с долей по РФ",
"weight": null,
"defaultWeight": 0.025,
"children": []
}
]
}
]
Should turn into:
[
{
"id": 1,
"name": "Блок «SoReX»",
"weight": null,
"defaultWeight": 0.3,
"children": [
{
"id": 1,
"name": "Планирование активностей",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 12.5
},
{
"id": 2,
"name": "Выполнение плана по визитам",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 12.5
},
{
"id": 3,
"name": "Выполнение плана по групповым мероприятиям",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 12.5
},
{
"id": 4,
"name": "Выполнение маркетинговой стратегии (включает три KPI)",
"weight": null,
"defaultWeight": 1,
"children": [
{
"id": 5,
"name": "Охват базы",
"weight": null,
"defaultWeight": 1,
"percent": 33.33,
"children": []
},
{
"id": 6,
"name": "Соблюдение кратности посещения специалистов",
"weight": null,
"defaultWeight": 1,
"percent": 33.33,
"children": []
},
{
"id": 7,
"name": "Интервальность",
"weight": null,
"defaultWeight": 1,
"percent": 33.33,
"children": []
}
]
{
"id": 14,
"name": "Время, проведённое на визитах в день",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 12.5
},
{
"id": 15,
"name": "Средняя длительность визита",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 12.5
},
{
"id": 16,
"name": "Доля рабочего дня на активности",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 12.5
},
{
"id": 17,
"name": "Геолокация",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 12.5
}
],
"percent": 30
},
{
"id": 2,
"name": "Блок «Качество»",
"weight": null,
"defaultWeight": 0.2,
"children": [
{
"id": 8,
"name": "% выполнения «Двойной визит» (оценка РМа)",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 20
},
{
"id": 9,
"name": "% выполнения «Аудит» (оценка РМа)",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 20
},
{
"id": 10,
"name": "% выполнения «Двойной визит» (оценка Аудитора)",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 20
},
{
"id": 11,
"name": "% выполнения «Аудит» (оценка Аудитора)",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 20
},
{
"id": 19,
"name": "Средневзвешенное с весами оценки РМа и Аудитора",
"weight": null,
"defaultWeight": 1,
"children": [],
"percent": 20
}
],
"percent": 20
},
{
"id": 3,
"name": "Блок «Рынок»",
"weight": null,
"defaultWeight": 0.5,
"children": [
{
"id": 26,
"name": "Выполнение плана продаж",
"weight": null,
"defaultWeight": 0.9,
"children": [],
"percent": 90
},
{
"id": 27,
"name": "Темп прироста",
"weight": null,
"defaultWeight": 0.025,
"children": [],
"percent": 2.5
},
{
"id": 28,
"name": "Evolution Index",
"weight": null,
"defaultWeight": 0.025,
"children": [],
"percent": 2.5
},
{
"id": 29,
"name": "Динамика фактической доли на рынке",
"weight": null,
"defaultWeight": 0.025,
"children": [],
"percent": 2.5
},
{
"id": 30,
"name": "Сравнение фактической доли на рынке с долей по РФ",
"weight": null,
"defaultWeight": 0.025,
"children": [],
"percent": 2.5
}
],
"percent": 50
}
]
I tried to solve this problem by recursion, but my knowledge of algorithms, unfortunately, leaves much to be desired
public setSum(weight: any, id?: number) {
const calculation = (weights) => weights.map(block => {
return {
...block,
percent: block.defaultWeight / this.sumBlock * 100
};
});
if (weight.length !== []) {
this.sumBlock = weight.reduce((acc, block) => {
return acc += block.defaultWeight;
}, 0);
if (id) {
this.cloneBlocks = this.cloneBlocks.map(item => {
if (item.id === id) {
return {
...item,
groups: weight.map(block => {
return {
...block,
percent: block.defaultWeight / this.sumBlock * 100
};
})
};
} else {
return { ...item };
}
});
return;
} else {
this.cloneBlocks = weight.map(block => {
return {
...block,
percent: block.defaultWeight / this.sumBlock * 100
};
});
}
}
weight.forEach(block => {
if (block.groups) {
this.setSum(block.groups, block.id);
}
});
console.log(this.cloneBlocks);
}
I think something like this should do the job, see comments for details on how it works:
// Start of Dataset
const object = [
{
"id": 1,
"name": "Блок «Тест1»",
"weight": null,
"defaultWeight": 0.3,
"children": [
{
"id": 1,
"name": "Планирование активностей",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 2,
"name": "Выполнение плана по визитам",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 3,
"name": "Выполнение плана по групповым мероприятиям",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 4,
"name": "Выполнение маркетинговой стратегии (включает три KPI)",
"weight": null,
"defaultWeight": 1,
"children": [
{
"id": 5,
"name": "Охват базы",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 6,
"name": "Соблюдение кратности посещения специалистов",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 7,
"name": "Интервальность",
"weight": null,
"defaultWeight": 1,
"children": []
}
],
"children": [
{
"id": 5,
"name": "Охват базы",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 6,
"name": "Соблюдение кратности посещения специалистов",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 7,
"name": "Интервальность",
"weight": null,
"defaultWeight": 1,
"children": []
}
]
},
{
"id": 14,
"name": "Время, проведённое на визитах в день",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 15,
"name": "Средняя длительность визита",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 16,
"name": "Доля рабочего дня на активности",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 17,
"name": "Геолокация",
"weight": null,
"defaultWeight": 1,
"children": []
}
]
},
{
"id": 2,
"name": "Блок «Тест2»",
"weight": null,
"defaultWeight": 0.2,
"children": [
{
"id": 8,
"name": "% выполнения «Двойной визит» (оценка РМа)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 9,
"name": "% выполнения «Аудит» (оценка РМа)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 10,
"name": "% выполнения «Двойной визит» (оценка Аудитора)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 11,
"name": "% выполнения «Аудит» (оценка Аудитора)",
"weight": null,
"defaultWeight": 1,
"children": []
},
{
"id": 19,
"name": "Средневзвешенное с весами оценки РМа и Аудитора",
"weight": null,
"defaultWeight": 1,
"children": []
}
]
},
{
"id": 3,
"name": "Блок «Тест3»",
"weight": null,
"defaultWeight": 0.5,
"children": [
{
"id": 26,
"name": "Выполнение плана продаж",
"weight": null,
"defaultWeight": 0.9,
"children": []
},
{
"id": 27,
"name": "Темп прироста",
"weight": null,
"defaultWeight": 0.025,
"children": []
},
{
"id": 28,
"name": "Evolution Index",
"weight": null,
"defaultWeight": 0.025,
"children": []
},
{
"id": 29,
"name": "Динамика фактической доли на рынке",
"weight": null,
"defaultWeight": 0.025,
"children": []
},
{
"id": 30,
"name": "Сравнение фактической доли на рынке с долей по РФ",
"weight": null,
"defaultWeight": 0.025,
"children": []
}
]
}
];
// Note: This function will mutate its parameter
function setPercent(dataset) {
// Sum the total defaultWeight for siblings
const totalWeight = dataset.reduce((acc, next) => acc + next.defaultWeight, 0);
dataset.forEach(node => {
// Set percent of siblings if totalWeight is different from 0
if (totalWeight !== 0) {
node.percent = node.defaultWeight / totalWeight * 100;
}
// Recurse for children
setPercent(node.children);
});
}
// Run function, but clone object to avoid mutation
const dataset = structuredClone(object);
setPercent(dataset);
console.log(dataset);