0

I have a situation where I need to zip two Objects together retaining both of the values. I can iterate through both the objects and build an array of all the keys.

    var traverse = function (obj, chain) {

        for (var prop in obj) {
            if (obj.hasOwnProperty(prop)) {

                var tempChain = [].concat(chain || []);
                tempChain.push(prop);

                if (typeof obj[prop] === 'object') {
                    traverse(obj[prop], tempChain);
                }
                console.log(tempChain);
            }
        }
    };

Passing in the following:

    traverse({
        'a': {
            'b': 'hello world',
            'b1': 'hello world 1',
            'c': {
                'd': 'dello'
            }
        }
    })

Will return me:

[a]
[a,b]
[a,b1]
[a,c]
[a, c, d]

So I now have an array of nested properties in an object. How can I access essentially obj[[a,c,d]]? I know I can solve the problem through eval but I can't trust the content.

eval('window.' + ['a','c','d'].join('.')); 

If I can loop through that array and check to see if the property exists in both of them, then build a new object of the combined 'zipped' values.

3
  • window !== obj, that wouldn't work anyway. But yes, you can use a simple loop. Commented Oct 4, 2013 at 12:12
  • Check any of these duplicates - just omit the .split(".") as you have an array already Commented Oct 4, 2013 at 12:19
  • I think this is some kind of XY problem. What exactly is your zip supposed to do, and why would you need property chains for that? Commented Oct 4, 2013 at 14:35

1 Answer 1

1

Perhaps something like this?

function getValueAt(obj, keyPathArray) {
    var emptyObj = {};

    return keyPathArray.reduce(function (o, key) {
        return (o || emptyObj)[key];
    }, obj);
}

Then you can use it like:

var o = { a: { c: { d: 1 } } };

getValueAt(o, ['a', 'c', 'd']); //1

However it's not efficient for non-existing properties, since it will not short-circuit. Here's another approach without using reduce:

function getValueAt(o, keyPathArray) {
    var i = 0, 
        len = keyPathArray.length;

    while (o != null && i < len) o = o[keyPathArray[i++]];

    return o;    
}
Sign up to request clarification or add additional context in comments.

4 Comments

Why not simply while (o!=null && i<l) o = o[keyPathArray[i++]];? Currently you will always return undefined when i exceeds the length, and it will fail when o becomes null somewhere.
I've tried using both your solutions however the function returns the value and I want the object pointing to the value. To give a better explanation heres some working code which are using evals. jsbin.com/EHeFayu/7
@Bergi, Yeah, somehow I haven't tought that the last value could be an object and that typeof null was 'object'. Silly mistakes. Fixed.
@dtsn, I cannot access jsbin right now, however I believe you could just ignore the last element in the array and it will return the object holding that property. var keyPath = ['a', 'b', 'c']; keyPath = keyPath.slice(0, keyPath.length - 1); getValueAt(o, keyPath); Obviously you have to hold a reference to the root object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.