从对象数组中创建具有相同键的值数组

3

我有一个对象数组,看起来像这样:

[
     {
      key1: val_1.a
      key2: val_2.a
      key3: val_3.a
     },{
      key1: val_1.b
      key2: val_2.b
      key3: val_3.b
     },{
      key1: val_1.c
      key2: val_2.c
      key3: val_3.c
     }
]

我想使用该对象创建另一个类似于以下内容的对象:
{ 
    key1: [val_1.a, val_1.b, val_1.c]
    key2: [val_2.a, val_2.b, val_2.c]
    key3: [[val_3.a, val_3.b, val_3.c]
}

既然每个对象中的键都相同,我只想将对应于每个键的所有值保存在数组中。

如果有人以前做过这件事并愿意分享代码,那就太好了。提前感谢。

4个回答

8
你可以这样做,以适用于所有浏览器,并且即使所有对象没有完全相同的键集(例如,它仅会累加存在的任何键的数据),也可以正常工作:
function combineKeyData(data) {
    var output = {}, item;
    // iterate the outer array to look at each item in that array
    for (var i = 0; i < data.length; i++) {
        item = data[i];
        // iterate each key on the object
        for (var prop in item) {
            if (item.hasOwnProperty(prop)) {
                // if this keys doesn't exist in the output object, add it
                if (!(prop in output)) {
                    output[prop] = [];
                }
                // add data onto the end of the key's array
                output[prop].push(item[prop]);
            }
        }
    }
    return output;
}

可运行的 jsFiddle: http://jsfiddle.net/jfriend00/0jjquju9/

解释:

  1. 对于数组中的每个项
  2. 对于数组中项的每个键
  3. 如果输出对象中不存在,则将该键作为空数组添加到输出对象中
  4. 将数据添加到输出对象中该键所在的数组末尾
  5. 返回新的结果对象

1
result = {};
for (var i = 0; i < array.length; i++) {
    var obj = array[i];
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (result[key]) {
                result[key].push(obj[key]);
            } else {
                retult[key] = [obj[key]];
            }
        }
    }
}

0
let R = require('ramda');
let arr =[
    {
     'key1': 'a',
     'key2': 'b',
     'key3': 'c',
    },{
     'key1': 'a1',
     'key2': 'b1',
     'key3': 'c1',
    },{
     'key1': 'a2',
     'key2': 'b2',
     'key3': 'c2',
    }
];

let key1 = R.pluck('key1', arr);
let key2 = R.pluck('key2', arr);
let key3 = R.pluck('key3', arr);
let obj = {
     key1,
     key2,
     key3
};

Obj = { key1: [ 'a', 'a1', 'a2' ], key2: [ 'b', 'b1', 'b2' ], key3: [ 'c', 'c1', 'c2' ] }

1
也许您可以解释一下您提出的解决方案,而不仅仅是发布一些代码?- 在review中发现。 - Brynden

0

var arr = [
 {
  key1: 'val_1.a',
  key2: 'val_2.a',
  key3: 'val_3.a'
 },{
  key1: 'val_1.b',
  key2: 'val_2.b',
  key3: 'val_3.b'
 },{
  key1: 'val_1.c',
  key2: 'val_2.c',
  key3: 'val_3.c'
 }
]

var result = arr.reduce(function(obj, current) { //Reduce the array to an object
    Object.keys(current).forEach(function(key) { //Each key
        obj[key] = obj[key] || []; //Has to be an array if not exists
        obj[key] = Array.isArray(obj[key]) ? obj[key] : [obj[key]]; //Has to be an array if not an array
        obj[key].push(current[key]); //Add current item to array of matching key
    });
    return obj; //Continue to the next object in the array
});

console.log(result);

以上函数:{{link1:Array#reduce}}, {{link2:Array#forEach}}, {{link3:Array.isArray}}, {{link4:Object.keys}} 都是 ECMAScript 5 规范的一部分,因此在 IE8 及以下版本中不可用。

1
这将返回一个二维数组,他想要一个包含数组的对象。 - Barmar
这也假设原始数组中的所有对象都具有完全相同的键集 - 既不多也不少。这是一种对于OP的确切数据而言是正确的快捷方式,但并不是构建输出数据结构的最安全方式。 - jfriend00
@jfriend00 现在它不再这样了。 - Madara's Ghost
如果结果要有意义,那似乎是必须的。否则,生成的子数组中元素之间的对应关系将会出错。 - Barmar
这不太好。例如,值为null。你应该优化你的代码。 - Zvezdas1989

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