简体   繁体   中英

How does one incrementally build a nested object structure from an array of property names?

My task is straight forward. I have an array of strings:

let a=["a","b","c"];

And i want to convert that array to (can alter the original array, doesn't matter) what i would like to call as "recursive object" just so:

//in json format just to demonstrate
"object": {
    "a": {
      "b":{
        "c":{
          
        }
        
      }
    }
  }

I've tried the following logic but couldn't get it to work due to reference problem and i couldn't build recursion.

let tempObj;
let obj2;

array.slice().reverse().forEach(function(item,index){
    
        obj2=tempObj;
        tempObj[item]="";
      
    });

Just to make sure we are on the same page, another example:

let arr=["alpha","beta","gamma"];
let magicObj=someMagicFunction(arr);
//magicObj["alpha"]["beta"]["gamma"] contains the value ""

Thanks

Start aggregating your object from the array's right most side via reduceRight and provide eg an empty object / {} or an empty string / "" as this method's initial value(s)...

 console.log( 'object:', ["a","b","c"].reduceRight((obj, key) => ({ [key]: obj }), {} ) ); console.log( 'object:', ["alpha","beta","gamma"].reduceRight((obj, key) => ({ [key]: obj }), "" ) );
 .as-console-wrapper { min-height: 100%;important: top; 0; }

... and since code code-reuse always should be a goal the above examples change to...

 function createObjectWithParentKeyAndChildValue(value, key) { return { [key]: value }; } console.log( 'object:', ['a', 'b', 'c'].reduceRight(createObjectWithParentKeyAndChildValue, {}) ); console.log( 'object:', ['alpha', 'beta', 'gamma'].reduceRight(createObjectWithParentKeyAndChildValue, '') );
 .as-console-wrapper { min-height: 100%;important: top; 0; }

Here is a simple solution:

 const arr = ["a","b","c"]; const result = arr.reverse().reduce((obj, key) => ({[key]: obj}), {}) console.log(result)

Here a little explaination:
o is the result of the last iteration and v is the current element in the array. {[v]: o} creates a new object and sets the property v to o and returns that.

let magicObj = arr.reverse().reduce((obj, prop) => ({ [prop]: obj }), {})

there is my pure recursive answer:

let a=["a","b","c"];

const b = (arr = [], obj = null) => {
  if (arr.length > 0) {    
    const { length, [length - 1]: last, ...r } = arr;
    const rest = Object.values(r);
    const nextObj = obj ? { [last]: obj } : { [last]: {} };
    return b(rest, nextObj);
  }
  return obj;
};

console.log(b(a));

The reduce / reduceRight answers are great. But this can also be done with a fairly trivial recursive version:

 const buildDeep = ([p, ...ps], val) => p == undefined? val: {[p]: buildDeep (ps, val)} console.log (buildDeep (['a', 'b', 'c'], {})) console.log (buildDeep (['alpha', 'beta', 'gamma'], ''))

To my mind, this is even simpler than reduce . It feels related to the various path-setting functions you see around, but is less complex since it doesn't have to work with an existing object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM