Any suggestions on how to get nested arrays / objects from the following array of objects?
[
{COLOR: "Black", FABRIC_DESIGN: "Leather", SIZE: "S"}
{COLOR: "Black", FABRIC_DESIGN: "Leather", SIZE: "L"}
{COLOR: "Black", FABRIC_DESIGN: "Velvet", SIZE: "S"}
{COLOR: "Black", FABRIC_DESIGN: "Velvet", SIZE: "M"}
{COLOR: "Red", FABRIC_DESIGN: "Velvet", SIZE: "S"}
]
What I am trying to get is:
[
{
label: "Black",
children: [
{ label: "Leather", children: [{ label: "S" }, { label: "L" }] },
{ label: "Velvet", children: [{ label: "S" }, { label: "M" }] }
]
},
{
label: "Red",
children: [{ label: "Velvet", children: [{ label: "S" }] }]
}
];
I managed to do it for objects with 2 properties but not more than that, and I cant figure out how to do it for objects with N properties.
2 Answers 2
You could do this using reduce and forEach methods and one object to keep the data of each level.
const data = [{COLOR: "Black", FABRIC_DESIGN: "Leather", SIZE: "S"},{COLOR: "Black", FABRIC_DESIGN: "Leather", SIZE: "L"},{COLOR: "Black", FABRIC_DESIGN: "Velvet", SIZE: "S"},{COLOR: "Black", FABRIC_DESIGN: "Velvet", SIZE: "M"},{COLOR: "Red", FABRIC_DESIGN: "Velvet", SIZE: "S"}]
const result = []
const levels = {result}
const keys = ['COLOR', 'FABRIC_DESIGN', 'SIZE']
data.forEach(o => {
keys.reduce((r, k, i, a) => {
const label = o[k];
if (!r[label]) {
const value = {label}
if (a[i + 1]) {
r[label] = {result: []}
value.children = r[label].result
}
r.result.push(value)
}
return r[label]
}, levels)
})
console.log(result)
answered May 13, 2020 at 19:21
Nenad Vracar
122k16 gold badges160 silver badges184 bronze badges
Sign up to request clarification or add additional context in comments.
2 Comments
Andreas
@brako Why did you accept a non-recursive answer when you explicitly ask for a recursive solution?
Nenad Vracar
@brako Feel free to accept the answer that works best for you and helps you to solve your problem. If you think you don't need recursion you can always edit your question.
EDIT : Now, you can specify the hierarchy.
var data = [
{COLOR: "Black", FABRIC_DESIGN: "Leather", SIZE: "S"},
{COLOR: "Black", FABRIC_DESIGN: "Leather", SIZE: "L"},
{COLOR: "Black", FABRIC_DESIGN: "Velvet", SIZE: "S"},
{COLOR: "Black", FABRIC_DESIGN: "Velvet", SIZE: "M"},
{COLOR: "Red", FABRIC_DESIGN: "Velvet", SIZE: "S"}
]
var hierarchy = ['COLOR', 'FABRIC_DESIGN', 'SIZE'];
// temporary object to make uniqu entries
var structuredDatas = {};
data.forEach(el => {
var editedDatas = structuredDatas;
for (depth of hierarchy) {
if (typeof el[depth] === 'undefined') {
break;
}
if (!editedDatas[el[depth]]) {
editedDatas[el[depth]] = { label: el[depth], children: {} };
}
editedDatas = editedDatas[el[depth]].children;
}
});
// all data are structured
// next, we format data as expected
var formattedDatas = Object.values(structuredDatas).map(formatLevel)
function formatLevel(datas) {
datas.children = Object.values(datas.children).map(formatLevel)
return datas
}
console.log(JSON.stringify(formattedDatas, null, 2));
3 Comments
btowers
it works for this specific example, but if the size of the objects is not 3 or the property name change it doesnt. What I am trying to achieve is for arrays with objects that have a variable number of properties and unknown property names.
wawan
I understand, but Json ‘s key order can’t be used, because keys are not ordered. You must specify somewhere the hierarchy.
btowers
I created the objects out of arrays like: ` [ { id: "COLOR", name: "Color", value_name: "Black" }, { id: "FABRIC_DESIGN", name: "Fabric", value_name: "Leather" }, { id: "SIZE", name: "Size", value_name: "S" } ]` Do you think I´d better work with the arrays insted of creating the objects?
Explore related questions
See similar questions with these tags.
lang-js
function groupBy(array, key) { /* ... */ return groupedArray; }. If this works then just use this same function for thechildrens of the groupedlabels