我有一个JavaScript对象数组,其结构如下:

objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];

我想从每个对象中提取一个字段,并获得一个包含值的数组,例如,字段foo将给出数组[1,3,5]。

我可以用这种简单的方法做到这一点:

function getFields(input, field) {
    var output = [];
    for (var i=0; i < input.length ; ++i)
        output.push(input[i][field]);
    return output;
}

var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]

是否有更优雅或更惯用的方法来实现这一点,从而不需要自定义实用程序函数?


注意建议的重复,它介绍了如何将单个对象转换为数组。


当前回答

谈到纯JS的解决方案,我发现,尽管它可能很不优雅,但简单的索引for循环比它的替代方案更具性能。

从100000个元素数组中提取单个属性(通过jsPerf)

传统循环368操作/秒

var vals=[];
for(var i=0;i<testArray.length;i++){
   vals.push(testArray[i].val);
}

ES6用于。。循环303操作/秒

var vals=[];
for(var item of testArray){
   vals.push(item.val); 
}

Array.prototype.map 19操作/秒

var vals = testArray.map(function(a) {return a.val;});

TL;DR-.map()很慢,但如果您觉得可读性比性能更重要,可以使用它。

编辑#2:6/2019-jsPerf链接断开,已删除。

其他回答

如果您希望ES6+中有多个值,以下操作将起作用

objArray = [ { foo: 1, bar: 2, baz: 9}, { foo: 3, bar: 4, baz: 10}, { foo: 5, bar: 6, baz: 20} ];

let result = objArray.map(({ foo, baz }) => ({ foo, baz }))

这是因为左边的{foo,baz}使用对象析构函数,而右边的箭头由于ES6的增强的对象文本而相当于{foo:foo,baz:baz}。

通常,如果您想要外推数组内的对象值(如问题中所述),那么可以使用reduce、map和数组析构函数。

ES6

let a = [{ z: 'word', c: 'again', d: 'some' }, { u: '1', r: '2', i: '3' }];
let b = a.reduce((acc, obj) => [...acc, Object.values(obj).map(y => y)], []);

console.log(b)

循环中使用的等效值为:

for (let i in a) {
  let temp = [];
  for (let j in a[i]) {
    temp.push(a[i][j]);
  }
  array.push(temp);
}

生成的输出:[“word”、“again”、“some”、“1”、“2”、“3”]

谈到纯JS的解决方案,我发现,尽管它可能很不优雅,但简单的索引for循环比它的替代方案更具性能。

从100000个元素数组中提取单个属性(通过jsPerf)

传统循环368操作/秒

var vals=[];
for(var i=0;i<testArray.length;i++){
   vals.push(testArray[i].val);
}

ES6用于。。循环303操作/秒

var vals=[];
for(var item of testArray){
   vals.push(item.val); 
}

Array.prototype.map 19操作/秒

var vals = testArray.map(function(a) {return a.val;});

TL;DR-.map()很慢,但如果您觉得可读性比性能更重要,可以使用它。

编辑#2:6/2019-jsPerf链接断开,已删除。

这取决于你对“更好”的定义。

其他答案指出了地图的使用,这是自然的(尤其是对于习惯于功能风格的人),而且简洁。我强烈建议您使用它(如果您不介意使用少数IE8-it人员)。所以,如果“更好”意味着“更简洁”、“可维护”和“可理解”,那么是的,它会更好。

另一方面,这种美丽不是没有额外成本的。我不太喜欢微面包,但我在这里做了一个小测试。结果是可以预测的,旧的丑陋的方式似乎比地图功能更快。所以,如果“更好”意味着“更快”,那么就不要,继续沿用老式的时尚。

同样,这只是一个微框架,绝不反对使用地图,这只是我的两分钱:)。

上面提供的答案适合于提取单个属性,如果您想从对象数组中提取多个属性,该怎么办。这就是解决方案!!在这种情况下,我们可以简单地使用_.pick(object,[paths])

_.pick(object, [paths])

假设objArray具有如下三个财产的对象

objArray = [ { foo: 1, bar: 2, car:10}, { foo: 3, bar: 4, car:10}, { foo: 5, bar: 6, car:10} ];

现在我们要从每个对象中提取foo和bar属性,并将它们存储在一个单独的数组中。首先,我们将使用map迭代数组元素,然后对其应用Lodash Library Standard_.pick()方法。

现在我们可以提取“foo”和“bar”属性。

var newArray=objArray.map((element)=>{return _.pick(element,['fo','bar'])})console.log(newArray);

结果是〔{foo:1,bar:2},{foo:3,bar:4},{foo:5,bar:6}〕

享受