将一个数组转换为对象数组

15

我如何将一个数组转换为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}

以此类推,对于其余数据也是如此。


一个数组本身就是一个对象。 - Sam I am says Reinstate Monica
3
你卡在哪了?看起来你需要迭代第一个数组来获取键,然后迭代其余的数组来获取值。你知道如何迭代数组吗?有一些指南可以解释这个问题:http://eloquentjavascript.net/chapter4.html。 - Felix Kling
你想要哪个:["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]] - crush
1
["fruits":"apple", 不合法。[{"fruits":"apple"}, 是合法的。 - Royi Namir
1
请注意,在您的“第一个对象作为”示例中,您的符号表示有误 - 对象应该用 { } 包裹,而不是数组 [ ] - John Carter
4个回答

10

演示

使用您提供的数据:

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()方法更优雅。 - Pavlo

8
如果同时使用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 } 
]

6
使用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;
});

Demo: http://jsfiddle.net/d7W76/2/


3
我同意更加优雅,但不幸的是,它在Chrome 31.0.1650中比较慢,速度慢了160倍。(也许我测试设置不对?我没想到会这样)此外,map()本质上仍然是一个封装的迭代器,所以你仍然要进行两次迭代。 - crush
@crush 你在那个测试中有点占我便宜了:http://jsperf.com/testing-map-foreach-vs-2x-for-statements/2 但是我的算法无论如何都要慢得多。显然,在V8和其他JavaScript引擎中,还有优化map()的空间。 - Pavlo
抱歉,那不是故意的 :D - crush
我试图使用上述数据制作堆叠面积图,但不知何故无法理解如何将数据用于堆叠条形图。http://bl.ocks.org/mbostock/3885211。 - user3084017

3

析构函数:

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)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接