最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Recursively creating a JSON tree, adding only at the deepest level - Stack Overflow

programmeradmin1浏览0评论

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. /

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/winduptoy/Mjq5D/2/

Share Improve this question edited Dec 30, 2012 at 3:06 371273 asked Dec 30, 2012 at 2:54 371273371273 5,44611 gold badges50 silver badges68 bronze badges 2
  • 1 Can you put together a working jsfiddle with all of the dependent libraries? – Jared Farrish Commented Dec 30, 2012 at 3:03
  • Whoops, sorry I forgot one, I added it to the bottom of the question. – 371273 Commented Dec 30, 2012 at 3:06
Add a ment  | 

3 Answers 3

Reset to default 3

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.

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;
   }
}

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;
    };
发布评论

评论列表(0)

  1. 暂无评论