Как получить и установить сумму значений объекта массива с бесконечной глубиной массива

Рейтинг: 0Ответов: 1Опубликовано: 21.08.2023

Мне нужно преобразовать массив объектов в новый массив с объектами включающими в себя новое поле типа "percent". Задача такая - у каждого объекта в массиве есть поле defaultWeight с числовым значением. В данном массиве я должен сложить defaultWeight текущего массива в сумму sumArray, далее я беру значение defaultWeight, делю на sumArray и умножаю на 100 (defaultWeight / sumArray) * 100. Таким образом я получаю процент числа которое должен поместить в новое поле "percent" какая глубина этих массивов бы не встретилась в будущем. Помогите, голову ломаю вторые сутки. Ниже пример:

[
    {
        "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": []
            }
        ]
    }
]

Должно превратиться в:

[
    {
        "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
    }
]

Ответы

▲ 0

addPercent добавляет поле percent в переданный массив.

const addPercent = a => {
    const s = a.reduce((acc, val) => acc + val['defaultWeight'], 0);
    for (const e of a) {
        e['percent'] = 100 * e['defaultWeight'] / s;
    }
};

traverse обходит структуру данных рекурсивно и вызывает cb для всех найденных массивов:

const traverse = (a, cb) => {
    cb(a);
    for (const e of a) {
        traverse(e['children'], cb);
    }
};

Использовать так:

const a = [...]; // тут должен быть ваш массив
traverse(a, addPercent);
console.log(JSON.stringify(a, undefined, 4));