So i have a json object that i would like to traverse and add all the nodes in a linear list.below is my json
[{ "name" : "Joe", "age" : "21", "children" : [
{ "name" : "Smith", "age" : "42", "children" : [] },
{ "name" : "Gary", "age" : "21", "children" : [
{ "name" : "Jenifer", "age" : "23", "children" : [
{ "name" : "Dani", "age" : "32", "children" : [] },
{ "name" : "Max", "age" : "34", "children" : [] }
]}
]}
]},
{ "name" : "Albert", "age" : "33", "children" : [] },
{ "name" : "Ron", "age" : "29", "children" : [] }
];
and i want to create a list of all objects present in the tree, objects need to be like this:
{ "name" : "Joe", "age" : "21"}
-
1Odd that these people have children older than themselves 😕Dave– Dave2016年07月28日 04:10:30 +00:00Commented Jul 28, 2016 at 4:10
-
Is there any ordering constraint? e.g. Joe is always the first, then followed by his descendants. This continues until no more children nodes are found until then the next node is Albert.Samuel Toh– Samuel Toh2016年07月28日 04:22:40 +00:00Commented Jul 28, 2016 at 4:22
-
no ordering constraintjosh_boaz– josh_boaz2016年07月28日 04:34:35 +00:00Commented Jul 28, 2016 at 4:34
4 Answers 4
Using a recursive function is an easy to traverse and flatten your array. Here's a sample algorithim:
function flatten(items, result = []) {
if (items.length) {
var item = items.shift();
result.push(item);
if (item.children && item.children.length) {
result = flatten(item.children, result);
}
return flatten(items, result);
} else {
return result;
}
}
var people = [{
"name": "Joe",
"age": "21",
"children": [{
"name": "Smith",
"age": "42",
"children": []
}, {
"name": "Gary",
"age": "21",
"children": [{
"name": "Jenifer",
"age": "23",
"children": [{
"name": "Dani",
"age": "32",
"children": []
}, {
"name": "Max",
"age": "34",
"children": []
}]
}]
}]
}, {
"name": "Albert",
"age": "33",
"children": []
}, {
"name": "Ron",
"age": "29",
"children": []
}];
console.log(flatten(people));
Comments
The easiest way to solve this would be to transverse your tree structure by using recursive function.
In my solution I make use of the instanceOf API to check what type of element the transverse is at and then determine what actions to be taken.
See:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/instanceof
Example:
let result = [];
let people =
[
{ "name" : "Joe", "age" : "21", "children" : [
{ "name" : "Smith", "age" : "42", "children" : [] },
{ "name" : "Gary", "age" : "21", "children" : [
{ "name" : "Jenifer", "age" : "23", "children" : [
{ "name" : "Dani", "age" : "32", "children" : [] },
{ "name" : "Max", "age" : "34", "children" : [] }
]}
]}
]},
{ "name" : "Albert", "age" : "33", "children" : [] },
{ "name" : "Ron", "age" : "29", "children" : [] }
];
function transverse(element, result) {
if (element instanceof Array)
element.forEach(item => { transverse(item, result); });
else if (element instanceof Object) {
result.push({ name: element.name, age: element.age });
if (element.hasOwnProperty("children")) {
transverse(element.children, result);
}
}
}
transverse(people, result);
console.log(result);
Output:
[ { name: 'Joe', age: '21' },
{ name: 'Smith', age: '42' },
{ name: 'Gary', age: '21' },
{ name: 'Jenifer', age: '23' },
{ name: 'Dani', age: '32' },
{ name: 'Max', age: '34' },
{ name: 'Albert', age: '33' },
{ name: 'Ron', age: '29' } ]
3 Comments
Assuming it's a simple traversal with no sorting it can be accomplished with two simple functions:
function visitChild(node, array) {
array[array.length] = { name: node.name, age:node.age };
if (node.children && node.children.length) {
node.children.forEach( function(child) { visitChild(child, array); } );
}
}
function traverseTree(root, list = []) {
if (root.length) {
root.forEach( function(node){ visitChild(node, list); });
}
return list;
}
console.log( traverseTree(tree) );
Comments
Since this has been brought back up, we might want to visit a simpler ES6 solution:
const extract = (people = []) =>
people .flatMap (({children = [], ... rest}) => [rest, ... extract (children)])
const people = [{name: "Joe", age: "21", children: [{name: "Smith", age: "42", children: []}, {name: "Gary", age: "21", children: [{name: "Jenifer", age: "23", children: [{name: "Dani", age: "32", children: []}, {name: "Max", age: "34", children: []}]}]}]}, {name: "Albert", age: "33", children: []}, {name: "Ron", age: "29", children: []}]
console .log (extract (people))
.as-console-wrapper {max-height: 100% !important; top: 0}
We implement a very simple (preorder) depth-first traversal of the hierarchy returning everything but the "children" property at each node.
Comments
Explore related questions
See similar questions with these tags.