In my application I create a JavaScript object based on a JSON response from the server similar to this:
{
name: "root",
id: 1,
children: [
{
name: "child one",
id: 11,
children: [
{name: "grand child 1", id: 111, children: []},
{name: "grand child 2", id: 112, children: []}
]
},
{
name: "child two",
id: 12,
children: []
}
]
}
I create a new node such as:
{name: "grandchild three", id: 113, children:[]}
With this in mind, how can I add this new grandchild to its parent with id 11? Please note that I don’t know the static path to node with id == 11
so I am wondering how I could obtain that node with just knowing it's id
.
Edit: please note the id's in the real case do NOT encode the path to objects. I created this simple example for demonstration of the data structure I am dealing with. But I can not retrieve the path to the object using its id in my real application.
In my application I create a JavaScript object based on a JSON response from the server similar to this:
{
name: "root",
id: 1,
children: [
{
name: "child one",
id: 11,
children: [
{name: "grand child 1", id: 111, children: []},
{name: "grand child 2", id: 112, children: []}
]
},
{
name: "child two",
id: 12,
children: []
}
]
}
I create a new node such as:
{name: "grandchild three", id: 113, children:[]}
With this in mind, how can I add this new grandchild to its parent with id 11? Please note that I don’t know the static path to node with id == 11
so I am wondering how I could obtain that node with just knowing it's id
.
Edit: please note the id's in the real case do NOT encode the path to objects. I created this simple example for demonstration of the data structure I am dealing with. But I can not retrieve the path to the object using its id in my real application.
Share Improve this question edited Oct 15, 2012 at 16:31 Aras asked Oct 15, 2012 at 16:08 ArasAras 5,9269 gold badges51 silver badges79 bronze badges 2 |5 Answers
Reset to default 9See this fiddle: http://jsfiddle.net/2Dvws/
It will find an object by ID. And push the new child. Since every object within Javascript is a reference, you can return it as an var.
var ob = {
name: "root",
id: 1,
children: [
{
name: "child one",
id: 11,
children: [
{
name: "grand child 1",
id: 111,
children: []},
{
name: "grand child 2",
id: 112,
children: []}
]},
{
name: "child two",
id: 12,
children: []}
]
};
The function which will return the found element. Will look into all child elements.
function findObjectById(root, id) {
if (root.children) {
for (var k in root.children) {
if (root.children[k].id == id) {
return root.children[k];
}
else if (root.children.length) {
return findObjectById(root.children[k], id);
}
}
}
};
var bla = findObjectById(ob, 111);
console.log(bla);
bla.children.push({
name: "child x",
id: 1111,
children: []
});
console.log(ob);
Output is that child with id 111 will have 1 child with id 1111
I assume the id consists of the parent-id plus the index (1 to 9) in the children array? Then you can go like that:
var rootobj = {…};
var newnode = {name: "grandchild three", id: 113, children:[]};
var id = ""+newnode.id;
var cur = [rootobj];
for (var i=0; i<id.length-i; i++)
cur = cur[id.charAt(i)-1].children;
cur[id.charAt(i)-1] = newnode;
Niels' answer is a good start, but doesn't fully traverse the tree (e.g. it will break if the node you're looking for is the child of the second child of the root). Also it breaks if the root is the id you're looking for. Here are my refinements:
function findObjectByID(root, id) {
if (root.name == id){
return root;
}
if (root.children) {
for (var k in root.children) {
if (root.children[k].name == id) {
return root.children[k];
}
else if (root.children[k].children) {
result = findObjectByID(root.children[k], id);
if (result) {
return result;
}
}
}
}
};
How about this.
for(var a = 0; a < object.length; a++) {
for(var b = 0; b < obj.children.length; b++) {
if(object[a].children[b].id == 11) {
object[a].children[b].children.push({
name: "grandchild three",
id: 113,
children: []
});
}
}
}
Here is a solution using object-scan. Using a library should make this a bit more readable and maintainable.
// const objectScan = require('object-scan');
const insert = (haystack, parentId, node) => objectScan(['**.id'], {
abort: true,
rtn: 'bool',
filterFn: ({ value, parent }) => {
if (value === parentId) {
parent.children.push(node);
return true;
}
return false;
}
})(haystack);
const obj = { name: 'root', id: 1, children: [ { name: 'child one', id: 11, children: [ { name: 'grand child 1', id: 111, children: [] }, { name: 'grand child 2', id: 112, children: [] } ] }, { name: 'child two', id: 12, children: [] } ] };
console.log(insert(obj, 11, { name: "grandchild three", id: 113, children: [] })); // true iff inserted
// => true
console.log(obj);
// => { name: 'root', id: 1, children: [ { name: 'child one', id: 11, children: [ { name: 'grand child 1', id: 111, children: [] }, { name: 'grand child 2', id: 112, children: [] }, { name: 'grandchild three', id: 113, children: [] } ] }, { name: 'child two', id: 12, children: [] } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>
Disclaimer: I'm the author of object-scan
object.children[0].children.push(newobject)
Where object is your original object and newobject is your new node. – user1726343 Commented Oct 15, 2012 at 16:10