Underscore.js:使用对象中的键创建映射表格

60

我正在使用优秀的Underscore.js库。我有一个特定的任务,用JavaScript或jQuery可以很好地完成,但我想知道是否有一些在Underscore中可用的抽象方法我错过了。

本质上,我有一个像这样的对象 -

var some_object_array = [{id: "a", val: 55}, {id: "b", val: 1}, {id: "c", val: 45}];

我想将这个转换成 -

var some_map = {"a": {id: "a", val: 55}, "b": {id: "b", val: 1}, "c": {id: "c", val: 45}};

我知道可以使用_.groupBy(some_object_array, "id")。但是这将返回一个类似于以下的映射 -

var some_grouped_map = {"a": [{id: "a", val: 55}], "b": [{id: "b", val: 1}], "c": [{id: "c", val: 45}]};
请注意,这段代码确实完成了它所宣传的工作。但我希望能够获得some_map而无需自己迭代对象。
任何帮助都将不胜感激。
6个回答

91

值得一提的是,自underscore.js之后,您现在可以使用_.object()函数。

var some_map = _.object(_.map(some_object_array, function(item) {
   return [item.id, item]
}));

8
对象映射非常有用,以至于我总是定义 mapo = _.compose(_.object, _.map); - Dustin Getz
似乎 _.object() 已被移除。在 underscore 中是否仍有替代方法可用? - Nick McCurdy
1
请纠正我,但我认为使用lodash时,您也可以使用单个_.transform函数。 - emkman
1
扩展@DustinGetz的评论... 也可以使用下划线混合代替将mapo分配给全局范围:_.mixin({mapo: _.compose( _.object, _.map )}); - Jordan Arsenault
3
_.object()在underscore的最新版本中没有被移除。 - svarog

49

对于你的情况,你应该使用indexBy函数:

var some_object_array = [{id: "a", val: 55}, {id: "b", val: 1}, {id: "c", val: 45}];

var some_grouped_map = _.indexBy(some_object_array, 'id');

最适合这种情况的答案 - user2846569
这是答案。 - Jeremy Iglehart
名称 some_grouped_map 令人困惑。indexBy 用于键唯一的情况。indexOf 用于非唯一键的分组。 - Edward Brey
1
自 lodash 4 开始,它是 _.keyBy来源 - Alexis Benoist

31

还有这种方法

_.reduce(data, function (o, item) { o[item.key] = item.value; return o }, {})

这是一个内部函数中包含两个语句的单个语句。


1
你不应该使用reduce,因为它用于不同的目的(将值列表归约为单个值),基本上这是一种hack,会导致其他开发人员阅读你的代码时产生很多困惑... - user2846569
6
它将一个列表缩减为一个单一的对象。完美应用了“reduce”函数。 - Otto Allmendinger
@OttoAllmendinger 然而,指定的缩减操作使用了异构参数,这是不常见的。在传统的缩减函数中,您希望您的 ab(这里是 oitem)具有相同的类型。事实上,强类型语言不允许像这里展示的这样的缩减函数。 - Milosz

13

我认为对于你的需求没有比groupBy更接近的东西了。即使有,它也不会比这个简单的方法更好:

var some_map = {};
_.each(some_object_array, function(val) {
  some_map[val.id] = val;
});

好的,那最终是我所做的。但我很好奇是否有更好的方法来完成它。 - Chantz
1
+1 因为我发现这种方法比 _.object(_.map(...)) 更直接。 - Courtney Christensen
这就是链式调用的作用 _.chain(data).map((val)=>[val.id, val]).object().value() - svarog

4
在这种情况下,您不需要迭代数组。不需要使用 map、reduce 或 transform。您所需要的只是旧版的 pluck。
_.object(_.pluck(some_object_array, 'id'), some_object_array);

2

对于ES6,它是

var some_map = _.chain(some_object_array)
                .map(item => [item.id, item])
                .object()
                .value()

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