xShirase
xShirase

Reputation: 12389

Create a dynamic nested object from array of properties

This sounds like a simple task, but I can't quite figure it out: I have an array :

var array = ['opt1','sub1','subsub1','subsubsub1']

From that I want to generate the following objects:

{
  opt1:{
    sub1:{
      subsub1:{
        subsubsub1:{}
      }
    }
  }
}

I have a way to do it, making a string and using eval, but I'm looking to avoid that, any idea?

Upvotes: 26

Views: 16438

Answers (5)

SeyyedKhandon
SeyyedKhandon

Reputation: 6093

As @p.s.w.g answer is a very good answer with pure js, but if you want an alternative with in a descriptive and functional way of that and set a value for final nested prop, you can use ramdajs assocPath https://ramdajs.com/docs/#assocPath like below:

var array = ['opt1','sub1','subsub1','subsubsub1'];

R.assocPath(array, "the value", {}); 

enter image description here

more details:

Makes a shallow clone of an object, setting or overriding the nodes required to create the given path, and placing the specific value at the tail end of that path. Note that this copies and flattens prototype properties onto the new object as well. All non-primitive properties are copied by reference.

examples:

R.assocPath(['a', 'b', 'c'], 42, {a: {b: {c: 0}}}); //=> {a: {b: {c: 42}}}

// Any missing or non-object keys in path will be overridden
R.assocPath(['a', 'b', 'c'], 42, {a: 5}); //=> {a: {b: {c: 42}}}

Upvotes: 0

Alexandre Pelagaggi
Alexandre Pelagaggi

Reputation: 421

You can use the following Function

function arr2nestedObject(myArray){
 var cp_myArray = myArray;
 var lastobj = {};
 while(cp_myArray.length>0){
    newobj = {};
    var prop = cp_myArray.pop();
    newobj[prop] = lastobj;
    lastobj = newobj;
 }
 return lastobj;
}

The following code:

var myArray = ["personal-information", "address", "street",'Great-Success'];
console.log(JSON.stringify(arr2nestedObject(myArray),undefined,2));

Would Produce the Following Output:

{
  "personal-information": {
   "address": {
    "street": {
     "Great-Success": {}
     }
    }
  }
}
Please let me know if that was what you meant.

Kind Regards.

Upvotes: 0

p.s.w.g
p.s.w.g

Reputation: 149010

You could use reduce:

var array = ['opt1','sub1','subsub1','subsubsub1'];
var object = {};
array.reduce(function(o, s) { return o[s] = {}; }, object);
console.log(object);

But this was only introduced in ECMAScript 5.1, so it won't be supported in some older browsers. If you want something that will be supported by legacy browsers, you could use the polyfill technique described in the MDN article above, or a simple for-loop, like this:

var array = ['opt1','sub1','subsub1','subsubsub1'];
var object = {}, o = object;
for(var i = 0; i < array.length; i++) {
    o = o[array[i]] = {};
}
console.log(object);

Upvotes: 42

le_m
le_m

Reputation: 20228

You can use reduceRight to transform the array into a 'chain' of objects:

const array = ['a', 'b', 'c'];
const object = array.reduceRight((obj, next) => ({[next]: obj}), {});

// Example:
console.log(object); // {"a":{"b":{"c":{}}}}

Upvotes: 10

Вадик Орлов
Вадик Орлов

Reputation: 346

you could use lodash set function

_.set(yourObject, 'a.b.c')

Upvotes: 7

Related Questions