Reputation: 1581
I have an array of objects. The objects may have a property called children which inturn would include an array of objects. It is effectively a tree of objects.
var my_array_of_objects=[
{
"object_info": "blah blah",
"children": [
{
"object_info": "blah blah",
"children": [
{
"object_info": "blah blah"
}
]
}
]
},
{
"object_info": "blah blah"
},
{
"object_info": "blah blah"
}
]
I am trying to recursively loop through the my_array_of_objects to return an array that will remove the tree architecture and give each object a relationship_id and a parent_relationship_id, however I am having a problem with the relationship_id getting set before the recursions happen and I can't see why... I assume it is a scoping issue?
function sort_relationships(objects, return_objects, parent_relationship_id, relationship_id){
$.each( objects, function( field_key, object ){
relationship_id++;
var new_object={};
new_object.relationship_id=relationship_id;
new_object.parent_relationship_id=parent_relationship_id;
new_object.object_info=object.object_info;
// PUSH OBJECT TO THE ARRAY TO BE RETURNED
return_objects.push(new_object);
// IF THE OBJECT HAS CHILDREN THEN RUN THE FUNCTION AGAIN WITH IT'S OBJECTS
if(object.children instanceof Array){
sort_relationships(object.children,return_objects,new_object.relationship_id,relationship_id);
}
});
return return_objects;
}
var my_new_array=sort_relationships(my_array_of_objects,[],0,0);
Based on the code above I would expect to have a unique relationship_id for each new object, however it is returning the following.
[
{
"relationship_id": 1,
"parent_relationship_id": 0,
"object_info": "blah blah"
},
{
"relationship_id": 2,
"parent_relationship_id": 1,
"object_info": "blah blah"
},
{
"relationship_id": 3,
"parent_relationship_id": 2,
"object_info": "blah blah"
},
{
"relationship_id": 2,
"parent_relationship_id": 0,
"object_info": "blah blah"
},
{
"relationship_id": 3,
"parent_relationship_id": 0,
"object_info": "blah blah"
}
]
I would expect to have the following:
[
{
"relationship_id": 1,
"parent_relationship_id": 0,
"object_info": "blah blah"
},
{
"relationship_id": 2,
"parent_relationship_id": 1,
"object_info": "blah blah"
},
{
"relationship_id": 3,
"parent_relationship_id": 2,
"object_info": "blah blah"
},
{
"relationship_id": 4,
"parent_relationship_id": 0,
"object_info": "blah blah"
},
{
"relationship_id": 5,
"parent_relationship_id": 0,
"object_info": "blah blah"
}
]
Upvotes: 0
Views: 1687
Reputation: 664599
You're doing relationship_id++
on a variable that is local to each recursive call, and is not reflected at the caller. You either need to return
the updated value, or just use a free variable:
function sort_relationships(objects) {
var return_objects = [];
var relationship_id = 0;
function recurse(objects, parent_relationship_id) {
$.each(objects, function(field_key, object) {
relationship_id++;
var new_object = {
relationship_id: relationship_id,
parent_relationship_id: parent_relationship_id,
object_info: object.object_info
};
// PUSH OBJECT TO THE ARRAY TO BE RETURNED
return_objects.push(new_object);
// IF THE OBJECT HAS CHILDREN THEN RUN THE FUNCTION AGAIN WITH IT'S OBJECTS
if (Array.isArray(object.children)) {
recurse(object.children, new_object.relationship_id);
}
});
}
recurse(objects, 0);
return return_objects;
}
var my_new_array=sort_relationships(my_array_of_objects);
Upvotes: 1
Reputation: 350310
You could use reduce
for this, and for the id (where things go wrong), you could add to the parent id the count of already accumulated objects:
function flatten(arr, parentId = 0) {
if (!arr) return [];
return arr.reduce ( function (acc, obj) {
var rel = {
object_info: obj.object_info,
relationship_id: parentId + acc.length + 1,
parent_relationship_id: parentId
};
return acc.concat([rel], flatten(obj.children, rel.relationship_id));
}, []);
}
// sample data
var my_array_of_objects=[{
"object_info": "blah blah",
"children": [{
"object_info": "blah blah",
"children": [{
"object_info": "blah blah"
}
]
}
]
}, {
"object_info": "blah blah"
}, {
"object_info": "blah blah"
}
];
// convert
var result = flatten(my_array_of_objects);
// output
console.log(result);
Upvotes: 1