Альтернативой предоставленным ответам будет сопоставление + уменьшение.
Вы можете отобразить свой массив в виде кусков объектов, похожих на результаты, которые вы можете глубоко объединить после:
const array = [
["plan_a", "tester_a", "product", "foo", "blocked", "5"],
["plan_a", "tester_a", "product", "foo", "passed", "10"],
["plan_a", "tester_a", "subproduct", "client", "passed", "15"],
["plan_a", "tester_b", "product", "bar", "blocked", "5"],
["plan_a", "tester_b", "product", "bar", "passed", "10"],
["plan_a", "tester_b", "subproduct", "server", "failed", "5"],
["plan_a", "tester_b", "subproduct", "server", "passed", "5"],
["plan_a", "tester_c", "product", "foo", "failed", "5"]
];
const result = array.map(mapIntoResultChunkShape).reduce(merge);
// ^^^^^ comes from lodash
function mapIntoResultChunkShape([
product,
tester,
categoryName,
categoryValue,
resultName,
resultValue
]) {
return {
[product]: {
[tester]: {
[categoryName]: {
[categoryName]: categoryValue,
[resultName]: resultValue
}
}
}
};
}
console.log(JSON.stringify(result, null, 2));
<script src="https://unpkg.com/lodash.merge@4.6.1/index.js"></script>
Основным преимуществом этого подхода является то, что он разделяет проблемы.Чтобы настроить этот код для любого другого преобразования массива-> объекта, все, что вам нужно сделать, это изменить способ отображения элемента массива в форму результата, то есть функцию mapIntoResultChunkShape
.
Вы также можете создать свойсобственная функция слияния, специализированная для вашего прецедента, которая может нести больше накладных расходов, чем использование более обобщенной библиотеки, созданной для обработки всех случаев:
const array = [
["plan_a", "tester_a", "product", "foo", "blocked", "5"],
["plan_a", "tester_a", "product", "foo", "passed", "10"],
["plan_a", "tester_a", "subproduct", "client", "passed", "15"],
["plan_a", "tester_b", "product", "bar", "blocked", "5"],
["plan_a", "tester_b", "product", "bar", "passed", "10"],
["plan_a", "tester_b", "subproduct", "server", "failed", "5"],
["plan_a", "tester_b", "subproduct", "server", "passed", "5"],
["plan_a", "tester_c", "product", "foo", "failed", "5"]
];
const result = array.map(mapIntoResultChunkShape).reduce(mergeResultChunkShapes);
function mapIntoResultChunkShape([
product,
tester,
categoryName,
categoryValue,
resultName,
resultValue
]) {
return {
[product]: {
[tester]: {
[categoryName]: {
[categoryName]: categoryValue,
[resultName]: resultValue
}
}
}
};
}
function mergeResultChunkShapes(item1, item2) {
if (
item1 === null ||
typeof item1 !== "object" ||
(item2 === null || typeof item2 !== "object")
) {
return item1 || item2;
}
const uniqueKeys = new Set(Object.keys(item1).concat(Object.keys(item2)));
return Array.from(uniqueKeys).reduce((res, key) => {
return Object.assign(res, {
[key]: mergeResultChunkShapes(item1[key], item2[key])
});
}, {});
}
console.log(JSON.stringify(result, null, 2));