Recursively creating a JSON tree, adding only at the deepest level

两盒软妹~` 提交于 2019-12-23 15:47:25

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!