1

Given the path "documents/settings/user"

How can this be made into a nested object

Result

{
   documents : {
         settings : {
               user : {}
          } 
    }
}

I can't think of how to reference each previous path

var dir = {};

var paths = "documents/settings/user".split('/')
for (var i = 0; i < paths.length; i++) {
  var path = paths[i];
  if(i === 0)
        dir[path] = {};
  //else
    //dir[path[i-?]] = {};
}

3 Answers 3

8

This is actually done quite easily with .reduce().

var dir = {}

var paths = "documents/settings/user".split('/')

paths.reduce(function(dir, path) {
  return dir[path] = {}
}, dir)

console.log(dir)

Because the first parameter is always the last value returned (or the first value provided), all we need to do is return the object being assigned to the current path. And because an assignment results in the value being assigned, we can use that as the expression of the return statement itself.


If needed, you can guard against empty path names due to adjacent separators.

var dir = {}

var paths = "documents///settings/user".split('/')

paths.reduce(function(dir, path) {
  return path ? (dir[path] = {}) : dir
}, dir)

console.log(dir)

Sign up to request clarification or add additional context in comments.

3 Comments

Very elegant solution. Just check Browser compatibility before using. You can even add polyfill for incompatible browsers
@Rajesh: Good point. Needs a patch for very old JS implementations.
Another great answer. Its ok I am on Node.js
3

Yet another elegant solution to build an object with value:

const buildObjWithValue = (path, value = '') => {
    const paths = path.split('.');
    return paths.reduceRight((acc, item, index) => ({
        [item]: index === paths.length - 1
            ? value
            : acc
    }), {});
}

For example buildObjWithValue('very.deep.lake', 'Baikal') gives us

{
  very: {
    deep: {
      lake: 'Bailkal'
    }
  }
}

Comments

1

Objects are passed by reference. You can use this feature and do something like this.

Array.forEach

var paths = "documents/settings/user".split('/')
var r = {};
var _tmp = r;
paths.forEach(function(el){
  _tmp[el] = {};
  _tmp = _tmp[el];
});

console.log(r)

For

var paths = "documents/settings/user".split('/')
var r = {};
var _tmp = r;
for(var i=0; i<paths.length; i++){
  _tmp = (_tmp[paths[i]] = {});
};

console.log(r)

1 Comment

Wow... really great. Thanks.

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.