0

I have problem with nested object in javascript. I want to generate, lets say, tree of objects. For example I have tree like this:

var tree = {
    item1: {
        item11: {},
        item12: {}
    },
    item2: {
        item21: {
            item211: {},
            item212: {}
        }
    }
}

Now I have path in string (like item1.item11) and I want to put item111 to tree object using path.

After calling treePush function I want this:

var tree = {
    item1: {
        item11: {
            item111: {}
        },
        item12: {}
    },
    item2: {
        item21: {
            item211: {},
            item212: {}
        }
    }
}

For now I have this piece of code, but this puts new item into root of tree not into desided level:

//use example: treePush('item1.item11', 'item111', tree);

function treePush(path, value, tree) {
    var branch = getBranch(path, tree);

    branch[value] = {};
    $.extend(tree, branch);

    return tree;
}

function search(key, tree) {
    //searches key in tree and generates path like 'item1.item11'
}

function getBranch(path, tree) {
    var keys = path.split('.'),
        obj = tree,
        branch = {};

    for(var i = 0; i < keys.length - 1; i++) {
        var key = keys[i];

        if (obj[key] === undefined) {
            return {};
        }

        branch[key] = obj[key]; 
        obj = obj[key];
    }

    return branch;
};

I think the problem is in line #5 of treePush function (branch[value] = {};) but I can't make it working. Any help appreciated.

zelazowy
  • 1,016
  • 2
  • 12
  • 26
  • Can you give an example of the `key` and `value` parameters that you're passing into `treePush()`? – Andy Aug 30 '13 at 13:58

2 Answers2

0

Use this:

Object.byString = function(o, s) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');
    while (a.length) {
        var n = a.shift();
        if (n in o) {
            o = o[n];
        } else {
            return;
        }
    }
    return o;
}


Object.byString(tree, 'item1.item11')['item111'] = {};

jsFiddle working example: http://jsfiddle.net/ehE8X/

Object.byString found here.

Community
  • 1
  • 1
Grigur
  • 465
  • 3
  • 6
0

As you stated, you want to select the path 'item1.item11' and push in there the given 'item111'. For this to work, you either have to specify the key/value to push, or just give it an object and mix that in the given path. The mixin approach requires jQuery for the $.extend method, which I don't like very much (to depend on jQuery for this simple task).

So here are both versions.

jQuery mixin version

var tree = {
    item1: {
        item11: {},
        item12: {}
    },
    item2: {
        item21: {
            item211: {},
            item212: {}
        }
    }
};

function treePush (tree, path, item) {
    var key, branch = tree;
    path = path.split('.');
    while (path.length) {
        key = path.shift();
        branch = branch[key] = branch[key] || {};
    }
    $.extend(branch, item);
}

treePush(tree, 'item1.item11', {item111: 'value'});
console.log(tree.item1.item11.item111 === 'value');

Specify target key in the path

var tree = {
    item1: {
        item11: {},
        item12: {}
    },
    item2: {
        item21: {
            item211: {},
            item212: {}
        }
    }
};

function treePush (tree, path, value) {
    var key, branch = tree;
    path = path.split('.');
    while (path.length > 1) {
        key = path.shift();
        branch = branch[key] = branch[key] || {};
    }
    branch[path.shift()] = value;
}

treePush(tree, 'item1.item11.item111', 'value');
console.log(tree.item1.item11.item111 === 'value');
Joni Bekenstein
  • 331
  • 1
  • 7