问题
I want to create a JSON hierarchy structure of unknown objects, so it must be handled recursively.
Here's my function, where angular.element.isEmptyObject() is inherited from jQuery, and angular.copy() is a function that creates a deep copy of the object (I'm using AngularJS).
function recurseTree(tree, newKey, newId) {
if(angular.element.isEmptyObject(tree)) {
tree[newKey] = {_id: newId};
} else {
for(var key in tree) {
if(typeof tree[key] == 'object') recurseTree(tree[key], newKey, newId);
else tree[newKey] = {_id: newId};
}
}
return angular.copy(tree);
}
Now run this:
var testT = {};
console.log(recurseTree(testT, 'a', '1'));
console.log(recurseTree(testT, 'b', '2'));
console.log(recurseTree(testT, 'c', '3'));
console.log(recurseTree(testT, 'd', '4'));
console.log(recurseTree(testT, 'e', '5'));
You'll notice that the first and second ones return as expected:
{
a: {
_id: '1',
b: {
_id: '2'
}
}
}
but the third one is where I run into trouble.
{
a: {
_id: '1',
b: {
_id: '2',
c: {
_id: '3'
}
},
c: {
_id: '3'
}
}
}
What do I need to fix to get the c object appended ONLY as a child of b, rather than also as a child of a? I'm stumped.
Here's a JSFiddle of it in action, check your console for the results. http://jsfiddle.net/winduptoy/Mjq5D/2/
回答1:
Try this:
function recurseTree(tree, newKey, newId) {
if(angular.element.isEmptyObject(tree)) {
tree[newKey] = {_id: newId};
return;
}
var child = null; // find current tree's child
for(var key in tree) {
if (key != '_id') {
child = tree[key]; // found a child
break;
}
}
if (child) { // recursively process on child
recurseTree(child, newKey, newId);
} else { // no child, so just fill the tree
tree[newKey] = {_id: newId};
}
}
Test:
var testT = {};
recurseTree(testT, 'a', '1');
console.log(testT);
recurseTree(testT, 'b', '1');
console.log(testT);
recurseTree(testT, 'c', '1');
console.log(testT);
recurseTree(testT, 'd', '1');
console.log(testT);
recurseTree(testT, 'e', '1');
console.log(testT);
Please be noted that I have not used angular.copy(tree) for the performance's sake.
If you don't want to change the tree, copy it before passing it to the function recurseTree. Please try it on jsFiddle.
回答2:
have a try? is it necessary to use for loop ?
for(var key in tree) {
if(typeof tree[key] == 'object'){
recurseTree(tree[key], newKey, newId);
break;
}
else {
tree[newKey] = {_id: newId};
break;
}
}
回答3:
My solution:
vm.getChilds = function (data, parent_id) {
return _.filter(data, function (item) {
return item.parent_id == parent_id;
});
};
vm.getIds = function (arr) {
var ids = [];
arr.forEach(function (item) {
ids.push(item.id);
});
return ids;
};
vm.updateList = function (data, arr) {
var ids = vm.getIds(arr);
var result = [];
data.forEach(function (item) {
if (ids.indexOf(item.id) == -1) {
result.push(item);
}
});
return result;
};
vm.getThree = function (data, parent_id) {
var items = vm.getChilds(data, parent_id);
if (items.length == 0) return null;
var tree = [];
var newData = vm.updateList(data, items);
items.forEach(function (item) {
item.sub_departments = vm.getThree(newData, item.id);
tree.push(item);
});
return tree;
};
来源:https://stackoverflow.com/questions/14087914/recursively-creating-a-json-tree-adding-only-at-the-deepest-level