Reputation: 783
I have a object which looks like this:
[
{
"id": 1,
"name": "Electronics",
"path": "Electronics",
"children": [
{
"id": 2,
"name": "Laptops & PC",
"path": "Electronics > Laptops & PC",
"children": []
},
{
"id": 7,
"name": "Phones & Accessories",
"path": "Electronics > Phones & Accessories",
"children": [
{
"id": 8,
"name": "Smartphones",
"path": "Electronics > Phones & Accessories > Smartphones",
"children": [
{
"id": 9,
"name": "Android",
"path": "Electronics > Phones & Accessories > Smartphones > Android",
"children": []
},
{
"id": 10,
"name": "iOS",
"path": "Electronics > Phones & Accessories > Smartphones > iOS",
"children": []
}
]
}
]
}
]
},
{
"id": 11,
"name": "Software",
"path": "Software",
"children": []
}
]
And I wanted to convert it to something like this:
[
{header: 'Electronics'},
{name: 'Laptops & PC', group: 'Electronics', id: 2},
{name: 'Phones & Accessories', group: 'Electronics', id: 7},
{name: 'Smartphones', group: 'Phones & Accessories', id: 8},
{name: 'Android', group: 'Smartphones', id: 9},
{name: 'iOS', group: 'Smartphones', id: 10},
{divider: true},
{name: 'Software', group: 'Software', id: 11}
]
Basically,
header
.group
{divider: true}
before proceeding to the next. (If it's the last root element, do not insert {divider: true}
While I was able to find lots of Hierarchical to JSON solutions on stackoverflow, I was not able to reverse engineer those solutions.
Can somebody please help me?
Upvotes: 1
Views: 960
Reputation: 386550
You could take an iterative and recursive approach by checking header keeping the corresponding divider and iterate children.
Then you need to add the standard object for any item.
The recursive callback uses a closure over the group. if not set, the group is a root item.
function getParts(array) {
var result = [];
array.forEach(function iter(group) {
return function ({ id, name, children }, i, { length }) {
if (!group && children.length) {
result.push({ header: name });
}
if (group || !children.length) {
result.push({ name, group: group || name, id });
}
children.forEach(iter(name));
if (!group && i + 1 !== length) {
result.push({ divider: true });
}
};
}(''));
return result;
}
var data = [{ id: 1, name: "Electronics", path: "Electronics", children: [{ id: 2, name: "Laptops & PC", path: "Electronics > Laptops & PC", children: [] }, { id: 7, name: "Phones & Accessories", path: "Electronics > Phones & Accessories", children: [{ id: 8, name: "Smartphones", path: "Electronics > Phones & Accessories > Smartphones", children: [{ id: 9, name: "Android", path: "Electronics > Phones & Accessories > Smartphones > Android", children: [] }, { id: 10, name: "iOS", path: "Electronics > Phones & Accessories > Smartphones > iOS", children: [] }] }] }] }, { id: 11, name: "Software", path: "Software", children: [] }, { id: 11, name: "Software", path: "Software", children: [] }, { id: 11, name: "Software", path: "Software", children: [] }],
result = getParts(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 56875
Here's a recursive approach using array.reduce
and the spread operator (...
) to flatten lists as you move through the data, and a separate helper function to take care of non-headers:
const flatten = data =>
data.reduce((a, e, i) => {
if (e.children.length) {
a.push({header: e.name});
a.push(...flattenR(e.children, e.name));
}
else {
a.push({name: e.name, group: e.name, id: e.id});
}
if (i < data.length - 1) {
a.push({divider: true});
}
return a;
}, [])
;
const flattenR = (data, grp) =>
data.reduce((a, e) => {
a.push({name: e.name, group: grp, id: e.id});
a.push(...flattenR(e.children, e.name));
return a;
}, [])
;
const data = [
{
"id": 1,
"name": "Electronics",
"path": "Electronics",
"children": [
{
"id": 2,
"name": "Laptops & PC",
"path": "Electronics > Laptops & PC",
"children": []
},
{
"id": 7,
"name": "Phones & Accessories",
"path": "Electronics > Phones & Accessories",
"children": [
{
"id": 8,
"name": "Smartphones",
"path": "Electronics > Phones & Accessories > Smartphones",
"children": [
{
"id": 9,
"name": "Android",
"path": "Electronics > Phones & Accessories > Smartphones > Android",
"children": []
},
{
"id": 10,
"name": "iOS",
"path": "Electronics > Phones & Accessories > Smartphones > iOS",
"children": []
}
]
}
]
}
]
},
{
"id": 11,
"name": "Software",
"path": "Software",
"children": []
}
];
console.log(flatten(data));
Upvotes: 1