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

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

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

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 ""

谢谢

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

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

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

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

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

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

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

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

这是我的纯递归答案:

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

reduce / reduceRight 的回答很棒。但这也可以用一个相当简单的递归版本来完成:

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

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

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