Search code examples
javascriptobject

Javascript: How to create an object from a dot separated string?


I ran into this potential scenario that I posed to a few of my employees as a test question. I can think of a couple ways to solve this problem, but neither of them are very pretty. I was wondering what solutions might be best for this as well as any optimization tips. Here's the question:

Given some arbitrary string "mystr" in dot notation (e.g. mystr = "node1.node2.node3.node4") at any length, write a function called "expand" that will create each of these items as a new node layer in a js object. For the example above, it should output the following, given that my object name is "blah":

blah: { node1: { node2: { node3: { node4: {}}}}}

From the function call:

mystr = "node1.node2.node3.node4";
blah = {};
expand(blah,mystr);

Alternately, if easier, the function could be created to set a variable as a returned value:

mystr = "node1.node2.node3.node4";
blah = expand(mystr);

Extra credit: have an optional function parameter that will set the value of the last node. So, if I called my function "expand" and called it like so: expand(blah, mystr, "value"), the output should give the same as before but with node4 = "value" instead of {}.


Solution

  • Here's a method that popped up in my mind. It splits the string on the dot notation, and then loops through the nodes to create objects inside of objects, using a 'shifting reference' (not sure if that's the right term though).

    The object output within the function contains the full object being built throughout the function, but ref keeps a reference that shifts to deeper and deeper within output, as new sub-objects are created in the for-loop.

    Finally, the last value is applied to the last given name.

    function expand(str, value)
    {
        var items = mystr.split(".") // split on dot notation
        var output = {} // prepare an empty object, to fill later
        var ref = output // keep a reference of the new object
    
        //  loop through all nodes, except the last one
        for(var i = 0; i < items.length - 1; i ++)
        {
            ref[items[i]] = {} // create a new element inside the reference
            ref = ref[items[i]] // shift the reference to the newly created object
        }
    
        ref[items[items.length - 1]] = value // apply the final value
    
        return output // return the full object
    }
    

    The object is then returned, so this notation can be used:

    mystr = "node1.node2.node3.node4";
    blah = expand(mystr, "lastvalue");