【问题标题】:Convert an array to an array of objects将数组转换为对象数组
【发布时间】:2014-01-15 11:10:08
【问题描述】:

如何将数组转换为 JavaScript 对象数组。

例如我有一个数组

data = [
    ["fruits","frozen","fresh","rotten"],
    ["apples",884,494,494],
    ["oranges",4848,494,4949],
    ["kiwi",848,33,33]
]

我想将其转换为名称值对。

例如,结果集合中的第一个对象是

 {"fruits": "apple", "frozen": 884, "fresh": 494, "rotten": 494}

其余数据依此类推。

【问题讨论】:

  • 你不需要转换。一个数组已经是一个对象
  • 你到底卡在哪里了?看起来您必须遍历键的第一个数组和所有其他数组才能获取值。你知道如何迭代数组吗?有指南解释说:eloquentjavascript.net/chapter4.html.
  • 你想要:["fruits":"apples","frozen":884,"fresh":494,"rotten":494],["fruits":"oranges","frozen":4848,"fresh":494,"rotten":4949] 还是["fruits":["apples", "oranges"],"frozen":[884, 4848],"fresh":[494,494],"rotten":[494,4949]]
  • ["fruits":"apple", 不合法。 [{"fruits":"apple"}, 确实
  • 请注意,您在“第一个对象作为”示例中的符号错误 - 对象包含在 { } 中,数组在 [ ]

标签: javascript arrays name-value


【解决方案1】:

破坏:

const data = [
    ["fruits","frozen","fresh","rotten"],
    ["apples",884,494,494],
    ["oranges",4848,494,4949],
    ["kiwi",848,33,33]
]
const titles = data[0]
const obj = data.slice(1).map(([fruits,frozen,fresh,rotten]) => ({ fruits,frozen,fresh,rotten }) )
console.log(obj)

【讨论】:

    【解决方案2】:

    如果同时使用map和reduce,解决方案会变得非常优雅:

    var collection = [
        ["fruits","frozen","fresh","rotten"],
        ["apples",884,494,494],
        ["oranges",4848,494,4949],
        ["kiwi",848,33,33]
    ];
    
    var keys = collection.shift();
    collection = collection.map(function (row) {
        return keys.reduce(function (obj, key, i) {
          obj[key] = row[i];
          return obj;
        }, {});
    });
    

    输出:

    [ 
      { fruits: 'apples', frozen: 884, fresh: 494, rotten: 494 },
      { fruits: 'oranges', frozen: 4848, fresh: 494, rotten: 4949 },
      { fruits: 'kiwi', frozen: 848, fresh: 33, rotten: 33 } 
    ]
    

    【讨论】:

      【解决方案3】:

      使用shift() + map() + forEach() 可以避免重复两次:

      var data = [
          ["fruits","frozen","fresh","rotten"],
          ["apples",884,494,494],
          ["oranges",4848,494,4949],
          ["kiwi",848,33,33]
      ];
      
      var collection = data.slice(); // make a copy
      var keys = collection.shift();
      
      collection = collection.map(function (e) {
          var obj = {};
      
          keys.forEach(function (key, i) {
              obj[key] = e[i];
          });
      
          return obj;
      });
      

      演示:http://jsfiddle.net/d7W76/2/

      【讨论】:

      • 绝对更优雅,我同意。不幸的是,它是160x slower in Chrome 31.0.1650。 (也许我设置的测试错误?我没想到)另外,map() 本质上是一个封装的迭代,所以你仍然迭代两次。
      • @crush 你在那次测试中有点占我便宜:jsperf.com/testing-map-foreach-vs-2x-for-statements/2 但无论如何我的算法要慢得多。显然,在 V8 和其他 JS 引擎中,map() 有优化空间。
      • 很抱歉。这不是故意的:D
      • 我试图用上面的数据制作一个堆积面积图。但不知何故我无法理解如何将这些数据用于堆积条形数据。bl.ocks.org/mbostock/3885211.
      【解决方案4】:

      DEMO

      使用您提供的数据:

      var data = [
          ["fruits","frozen","fresh","rotten"],
          ["apples",884,494,494],
          ["oranges",4848,494,4949],
          ["kiwi",848,33,33]
      ]
      

      以下函数会将数组的第一个元素视为对象属性的键。然后它将遍历剩余的元素,并使用这些键将它们转换为对象。最后,它会返回一个包含这些新对象的数组。

      function convertToArrayOfObjects(data) {
          var keys = data.shift(),
              i = 0, k = 0,
              obj = null,
              output = [];
      
          for (i = 0; i < data.length; i++) {
              obj = {};
      
              for (k = 0; k < keys.length; k++) {
                  obj[keys[k]] = data[i][k];
              }
      
              output.push(obj);
          }
      
          return output;
      }
      

      输出

      [
          { fruits: 'apples', fresh: 494, frozen: 884, rotten: 494 },
          { fruits: 'oranges', fresh: 494, frozen: 4848, rotten: 4949 },
          { fruits: 'kiwi', fresh: 33, frozen: 848, rotten: 33 }
      ]
      

      【讨论】:

      • 赞成。使用两个 for 循环是最简单的解决方案,尽管我使用 map() 的方法更优雅,imo。
      猜你喜欢
      • 2021-05-03
      • 2018-12-04
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2018-10-13
      相关资源
      最近更新 更多