【问题标题】:Create a dynamic nested object from array of properties从属性数组创建动态嵌套对象
【发布时间】:2014-04-29 01:20:53
【问题描述】:

这听起来像是一个简单的任务,但我不太明白:我有一个数组:

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

从中我想生成以下对象:

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

我有办法做到这一点,制作一个字符串并使用 eval,但我希望避免这种情况,知道吗?

【问题讨论】:

    标签: javascript arrays object


    【解决方案1】:

    你可以使用reduce:

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

    但这仅在 ECMAScript 5.1 中引入,因此在某些较旧的浏览器中将不支持。如果你想要旧版浏览器支持的东西,你可以使用上面 MDN 文章中描述的 polyfill 技术,或者一个简单的for-loop,像这样:

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

    【讨论】:

    • 或者考虑.reduceRight(),这样返回值就是顶级对象。
    • 对我来说两者都无法正常工作...试试控制台...?!
    • @Beat 我已将代码块转换为 sn-ps,以便您可以看到它们的运行情况。如果您仍然遇到问题,请尝试将jsfiddle 放在一起,或通过 sn-p 提出问题,以证明什么不起作用 - 请随时在您的问题中参考此答案以进行澄清。
    • 好的。我使用的是 reduce 函数的返回对象,而不是 object 本身。但是您的修改现在让它更清晰了!
    【解决方案2】:

    您可以使用reduceRight 将数组转换为对象的“链”:

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

    【讨论】:

      【解决方案3】:

      你可以使用lodash设置函数

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

      【讨论】:

        【解决方案4】:

        可以使用以下函数

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

        以下代码:

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

        将产生以下输出:

        {
          "personal-information": {
           "address": {
            "street": {
             "Great-Success": {}
             }
            }
          }
        }
        
        如果那是你的意思,请告诉我。

        亲切的问候。

        【讨论】:

          【解决方案5】:

          由于@pswg 的答案是纯 js 的一个很好的答案,但是如果您想要以描述性和功能性的方式和set a value for final nested prop 替代,您可以使用ramdajs assocPath https://ramdajs.com/docs/#assocPath,如下所示:

          var array = ['opt1','sub1','subsub1','subsubsub1'];
          
          R.assocPath(array, "the value", {}); 
          

          更多详情:

          对对象进行浅层克隆,设置或覆盖节点 需要创建给定的路径,并将特定值放在 那条路的尽头。请注意,这会复制并展平 原型属性也添加到新对象上。所有非原始 属性是通过引用复制的。

          例子:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-09-04
            • 1970-01-01
            • 2019-10-06
            • 2021-11-28
            • 1970-01-01
            • 2021-11-02
            • 2013-10-11
            • 2020-12-21
            相关资源
            最近更新 更多