在JavaScript中,字典推导或对象`map`是什么?

94

我需要在JavaScript中从列表生成几个对象。在Python中,我会这样写:

{key_maker(x): val_maker(x) for x in a_list}

还有一种询问方式,是否存在类似于 jQuery.map() 但可聚合对象的方法?以下是我的猜测(不起作用):

var result = {}
$.map(a_list, function(x) {
    $.extend(result, {key_maker(x): val_maker(x)})
})

1
你的$.extend版本行不通。在对象字面量符号中,属性标识符不能是表达式的结果。这段代码会失败... {key_maker(x): val_maker(x)} - user1106925
7个回答

75

这里有一个不使用reduce的版本:

Object.fromEntries( a_list.map( x => [key_maker(x), value_maker(x)]) );

Object.fromEntries 基本上与 Lodash 中的 _.fromPairs 相同。 对我来说,这更像是 Python 字典推导。


2
在我看来,这是我们可以在没有特殊语法的情况下更接近理解的方式,尽管截至2019年1月,它仍然是一个提案,并未在NodeJS中实现。 - villasv
1
我认为这很像字典推导式,可能会成为被接受的答案。 - memo

62
假设 a_list 是一个数组,最接近的可能是使用 .reduce()
var result = a_list.reduce(function(obj, x) {
    obj[key_maker(x)] = val_maker(x);
    return obj;
}, {});

JavaScript 的未来版本可能会引入数组推导。


您可以使用MDN提供的兼容性补丁来修复不符合ES5标准的实现。


如果 a_list 不是一个数组,而是一个普通对象,你可以使用 Object.keys() 来执行相同的操作。
var result = Object.keys(a_list).reduce(function(obj, x) {
    obj[key_maker(a_list[x])] = val_maker(a_list[x]);
    return obj;
}, {});

如果使用的JS版本没有reduce,我认为jQuery也从未添加过它。但是underscore有它。 - Mark Reed
@MarkReed:没错。我更新了链接到MDN兼容性补丁。 - user1106925
jQuery目前还没有reduce方法。您可以在其trac中找到一些实现,链接为:http://bugs.jquery.com/ticket/1886 - Jeroen K
3
使用underscore或lodash,可以这样写:_.reduce(a_list, function(obj, x){ ... }, {});。其中的代码内容不予解释。 - metakermit
使用箭头符号和逗号运算符的稍短版本:a_list.reduce((o, x) => (o[key_maker(x)] = val_maker(x), o), {}) - Avner

8

虽然这是一个老问题,但在新版本的Javascript中答案略有变化。使用ES2015(ES6),您可以通过一行代码来实现对象推导:

a_list.reduce((obj, x) => Object.assign(obj, { [key_maker(x)]: value_maker(x) }), {})

6
也许可以这样做,使用 Lodash var result = _.fromPairs(a_list.map(x => [key_maker(x), value_maker(x)]));

6

ES5引入了一个Map用于有序字典。Map推导的语法如下:

Map( Array.map(function(o){return[ key_maker(o), val_maker(o) ]}))

例子:

> a_list = [ {x:1}, {x:2}, {x:3} ]
< [ Object, Object, Object ]
>
> let dict = new Map(a_list.map(function(o){return[ o.x, o.x**2 ]}))
< Map[3]
< 0 : {1 => 1}
< 1 : {2 => 4}
< 2 : {3 => 9}
>
> dict.get(2)
< 4

4
一种更短的 ES6 版本如下所示:
a_list.reduce((obj, x) => (obj[key_maker(x)] = val_maker(x), obj),{})

1

我正在使用最新版本的TypeScript并且我使用

const list = [1, 2, 3, ...];
const obj = Object.fromEntries(array.map(val, idx) => [func1(val), func2(val)]))
// python equivalent: {func1(x): func2(x) for x in a_list}

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