4
var params = {
    search: {
        make: "",
        model: ""
    }
}

function setVariable() {
    var value = "BMW";
    var key = "search.make";
    var arr = key.split(".");    //eg. ["search", "make"]
    params[arr[0]][arr[1]] = value;   // this works, but how do you
                                      // do it with unknown arr[] length?
}

How do I do this with an unknown arr[] length?

I have surmised that I probably need to do a recursive call, maybe passing something like arr.slice(1) within the function, but I have not been able to figure out what that should look like.

1
  • 2
    What if search does not even exist? Would you want to create the object {make: value} then and assign it to params.search? Or do you only want to be able to set the value for existing properties? Commented Mar 4, 2012 at 11:29

2 Answers 2

4
var params = {
    search: {
        make: "",
        model: "",
        whatever: {
            foo: {
                bar: {
                    moo: 123,
                    meow: 'xyz'
                }
            }
        }
    }
};

function updatePath(obj, path, value) {
    var parts = path.split('.');
    var i, tmp;
    for(i = 0; i < parts.length; i++) {
        tmp = obj[parts[i]];
        if(value !== undefined && i == parts.length - 1) {
            tmp = obj[parts[i]] = value;
        }
        else if(tmp === undefined) {
            tmp = obj[parts[i]] = {};
        }
        obj = tmp;
    }
    return obj;
}

Demo:

> updatePath(params, 'search.whatever.foo.bar')
{ moo: 123, meow: 'xyz' }
> updatePath(params, 'search.whatever.foo.bar.moo')
123
> updatePath(params, 'search.whatever.foo.bar.moo', 'test')
'test'
> updatePath(params, 'search.whatever.foo.bar.moo')
'test'
> updatePath(params, 'search.whatever.foo.bar')
{ moo: 'test', meow: 'xyz' }
> updatePath(params, 'search.whatever.foo.bar.x.y.z', 'hi')
'hi'
> updatePath(params, 'search.whatever.foo.bar.x')
{ y: { z: 'hi' } }
> updatePath(params, 'search.whatever.foo.bar')
{ moo: 'test',
  meow: 'xyz',
  x: { y: { z: 'hi' } } }
>
Sign up to request clarification or add additional context in comments.

Comments

2

The following code traverses your params object until the given key is found. It assumes that key.split(".") returns a proper array of keys (so you might need to sanitize your inputs here further.

var params = {
    search: {
        make: "",
        model: ""
    }
}

function setVariable() {
    var value = "BMW";
    var key = "search.make";
    var arr = key.split(".");    //eg. ["search", "make"]

    var runner = params;
    for( var i=0, max=arr.length-1; i<max; ++i ) {
       // make sure the key exists
       runner[ arr[i] ] = runner[ arr[i] ] || {};
       // move one level deeper
       runner = runner[ arr[i] ];
    }

    // set the value in the last level
    runner[ arr[arr.length-1] ] = value;   
}

EDIT: wrt to the comment of Felix Kling: It assumes that you want previously not existant keys to be generated. Else you would have to put a a further check into the for loop and leave the function, if the key does not exist, instead of creating it.

2 Comments

Won't this set the value of the runner variable, rather than the original params variable?
As it is always working ob objects, both runner and params always point to the same object or a part of it respectively. An expression like runner = 3; would break this connection, but adding a new key to the object does not. So the above script should add values to the original object after all. [fixing a typo, too]

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.