从对象数组中,将属性的值提取为数组

IT技术 javascript javascript-objects
2020-12-16 23:10:28

我有具有以下结构的 JavaScript 对象数组:

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

我想从每个对象中提取一个字段,并获取一个包含值的数组,例如 fieldfoo会给出 array [ 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 ]

是否有更优雅或惯用的方法来执行此操作,以便不需要自定义实用程序函数?


请注意建议的 duplicate,它涵盖了如何将单个对象转换为数组。

6个回答

这是实现它的更短的方法:

let result = objArray.map(a => a.foo);

或者

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

您也可以检查Array.prototype.map()

嗯,这与 totymedli 的另一个答案的评论相同,但尽管如此,它实际上比其他答案更好(在我看来),所以......将其更改为接受的答案。
2021-02-09 23:10:28
@Alnitak在我的观点使用较新的功能,客观的更好。这个片段非常常见,所以我不相信这是抄袭。将过时的答案固定在顶部并没有任何value。
2021-02-10 23:10:28
2021-02-13 23:10:28
我真的很喜欢那个,顺便说一句,那个=>符号对我来说闻起来像是新事物,所以我认为如果该解决方案实际上可行,则需要对其兼容性进行审查。
2021-02-15 23:10:28
当然,这是允许的,但恕我直言,没有什么可以客观地使这个答案更好,只是它使用了在您提出问题时不可用的语法,并且在某些浏览器中甚至不受支持。我还注意到,这个答案是在这个答案发布前近一年对最初接受的答案所做评论的直接副本。
2021-03-01 23:10:28

是的,但它依赖于 JavaScript 的 ES5 特性。这意味着它不能在 IE8 或更旧的版本中工作。

var result = objArray.map(function(a) {return a.foo;});

在 ES6 兼容的 JS 解释器上,为了简洁起见,您可以使用箭头函数

var result = objArray.map(a => a.foo);

Array.prototype.map 文档

说到 JS 唯一的解决方案,我发现,尽管可能不优雅,但简单的索引for循环比它的替代方案更高效。

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

传统 for 循环368 Ops/sec

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

ES6 for..of 循环303 Ops/sec

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 链接已损坏,已删除。

我刚刚用jsBench重新测试了它(非常感谢Mirko Vukušić创建了jsPerf的替代品),结果仍然相同-for是最快的,for .. of稍慢,map大约慢了一半。
2021-02-11 23:10:28

查看Lodash 的_.pluck()函数或Underscore_.pluck()函数。两者都可以在单个函数调用中完成您想要的操作!

var result = _.pluck(objArray, 'foo');

更新: _.pluck()已从 Lodash v4.0.0 中删除,有利于_.map()与类似于Niet's answer 的内容结合使用_.pluck()在 Underscore 中仍然可用

更新 2:正如 Mark在评论中指出的那样,在 Lodash v4 和 4.3 之间的某个地方,添加了一个新功能,再次提供此功能。_.property()是一个速记函数,它返回一个用于获取对象中属性值的函数。

此外,_.map()现在允许将字符串作为第二个参数传入,该参数传入_.property(). 因此,以下两行代码等效于上述 Lodash 4 之前的代码示例。

var result = _.map(objArray, 'foo');
var result = _.map(objArray, _.property('foo'));

_.property(),因此_.map(),还允许您提供点分隔的字符串或数组以访问子属性:

var objArray = [
    {
        someProperty: { aNumber: 5 }
    },
    {
        someProperty: { aNumber: 2 }
    },
    {
        someProperty: { aNumber: 9 }
    }
];
var result = _.map(objArray, _.property('someProperty.aNumber'));
var result = _.map(objArray, _.property(['someProperty', 'aNumber']));

_.map()上面示例中的两个调用将返回[5, 2, 9].

如果您更喜欢函数式编程,请查看Ramda 的 R.pluck()函数,它看起来像这样:

var result = R.pluck('foo')(objArray);  // or just R.pluck('foo', objArray)

最好使用诸如 lodash 或 underscore 之类的库来确保跨浏览器。

在 Lodash 中,您可以通过以下方法获取数组中属性的值

_.map(objArray,"foo")

并在下划线

_.pluck(objArray,"foo")

两者都会回来

[1, 2, 3]