0

I have been struggling with this problem the entire day. I feel like it's super solvable, and I'm not sure where I'm going wrong. Each time I go to post this, I feel like I come up with a different solution that doesn't end up working.

I'm looking to do the following:

var someObj = {};

// @param key - string - in the form of "foo-bar-baz" or "foo-bar". 
// (i won't know the number of segments ahead of time.)
// @param value - string - standard, don't need to act on it

function buildObject( key, value ) {

  var allKeys = key.split("-");

  // do stuff here to build someObj

}

Essentially the key will always take the format of key-key-key where i want to build someObj[key1][key2][key3] = value.

This JSFiddle contains a longer example with a sample layout of the data structure I want to walk away with.

Thanks so much for any help you can give.

2 Answers 2

2
var someObj = {};

// @param key - string - in the form of "foo-bar-baz" or "foo-bar". 
// (i won't know the number of segments ahead of time.)
// @param value - string - standard, don't need to act on it
function buildObject( key, value ) {

  var allKeys = key.split("-");
  var container, i, n;
  for (container = someObj, i = 0, n = allKeys.length; i < n - 1; ++i) {
    var keyPart = allKeys[i];
    container = Object.hasOwnProperty.call(container, keyPart)
        ? container[keyPart] : (container[keyPart] = {});
  }
  container[allKeys[n - 1]] = value;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Wow, magical. Any reason you used call instead of doing container.hasOwnProperty(keyPart)? Also, if it's possible to explain simply without too much effort, why alias someObj instead of extending it directly?
@Joshua Cody, I use Object.hasOwnProperty.call so that buildObject("hasOwnProperty", 42) doesn't break all subsequent calls to buildObject.
@Joshua Cody, to answer the second part of your question, container always points to the object that should contain allKeys[i] so it only aliases someObj the first time through the loop. If I didn't use a separate variable to track it, I would lose the root by the time I got to the end of the loop.
Awesome, Mike. I caught on to what you were doing finally once I went through the code a few times. So that's the actually magic of the solution, making sure you update the variable to point at the current location. Again, thanks so much. Your solution is helpful and elegant.
0

I came up with http://jsfiddle.net/XAn4p/ before i saw Mike's answer. I'm posting just for another way.

var newObj = function ()
    {};
newObj.prototype = 
    {
        addToObject: function (keys, value)
        {
            var keySplit = keys.split("-",2);
            if (keySplit.length  > 1)
            {
                if(this[keySplit[0]] == null)
                {
                   this[keySplit[0]] = new newObj();
                }
                var newKeys = keys.substr(keySplit[0].length +1);
                this[keySplit[0]].addToObject(newKeys, value);
            }
            else
            {
               this[keySplit[0]] = value 
            }
        }
    };

var obj = new newObj();

Comments

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.