如何从属性名称数组逐步构建嵌套对象结构?

问题描述

我的任务很简单。我有一个字符串数组:

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

而且我想将该数组转换为(可以更改原始数组,无所谓)我想称之为“递归对象”的内容

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

我已经尝试了以下逻辑,但由于引用问题而无法使其正常工作,并且我无法构建递归。

let tempObj;
let obj2;

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

只是为了确保我们在同一页面上,再举一个例子:

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

谢谢

解决方法

通过 reduceRight 从数组的最右侧开始聚合您的对象并提供例如空对象/{} 或空字符串/"" 作为此方法的初始值...

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

... 并且由于代码代码重用始终应该是目标,因此上面的示例更改为...

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; }

,

这是一个简单的解决方案:

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

这里稍微解释一下:
o 是最后一次迭代的结果,v 是数组中的当前元素。 {[v]: o} 创建一个新对象并将属性 v 设置为 o 并返回。

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

这是我纯粹的递归答案:

let a=["a","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));
,

reduce / reduceRight 的答案很棒。但这也可以通过相当简单的递归版本来完成:

const buildDeep = ([p,...ps],val) =>
  p == undefined ? val : {[p]: buildDeep (ps,val)}

console .log (buildDeep (['a','c'],{}))
console .log (buildDeep (['alpha','gamma'],''))

在我看来,这比 reduce 更简单。它感觉与您所看到的各种路径设置功能有关,但并不复杂,因为它不必与现有对象一起使用。