JavaScript中将Underscore数组转换为对象

15

使用Underscore有没有一种简单/清晰的方法可以将此内容转换为

[ { id: 'medium', votes: 7 },
  { id: 'low',    votes: 9 },
  { id: 'high',   votes: 5 } ]

进入

 { 'low'    : 9,
   'medium' : 7,
   'high'   : 5 }
8个回答

43

你可以考虑使用 _.indexBy(...)

var data = [{
    id: 1,
    name: 'Jon Doe',
    birthdate: '1/1/1991',
    height: '5 11'
}, {
    id: 2,
    name: 'Jane Smith',
    birthdate: '1/1/1981',
    height: '5 6'
}, {
    id: 3,
    name: 'Rockin Joe',
    birthdate: '4/4/1994',
    height: '6 1'
}, {
    id: 4,
    name: 'Jane Blane',
    birthdate: '1/1/1971',
    height: '5 9'
}, ];

var transformed = _.indexBy(data, 'id');

这里有一个代码片段: https://jsfiddle.net/4vyLtcrf/3/

更新: 在 Lodash 4.0.1 中,方法 _.indexBy 已更名为 _.keyBy


值得注意的是,生成的对象中仍然会包含id属性,但在大多数情况下这应该是可以接受的(在其他情况下也很容易进行后排除)。 - peterp
对于那些希望将最终对象中的每个键作为该键的项目数组(而不是单个项目)的人,也有_.groupBy()提供了类似的解决方案。 - Hartley Brody

17
var data = [ { id: 'medium', votes: 7 },
  { id: 'low',    votes: 9 },
  { id: 'high',   votes: 5 } ];

你可以使用 _.map_.values_.object 来完成此操作,像这样:

console.log(_.object(_.map(data, _.values)));
# { medium: 7, low: 9, high: 5 }

解释

我们使用map函数将values函数(该函数获取给定对象的所有值)应用于data的所有元素,从而得到:

# [ [ 'medium', 7 ], [ 'low', 9 ], [ 'high', 5 ] ]

然后我们使用 object 函数将其转换为对象。


一个有趣的回答,但也许你可以先澄清一下数据是什么,例如数据 = x; - dewd
我使用了Krasimir的答案,但你用下划线回答了这个问题,对于任何对此感兴趣的人来说,还有更多可以学习的东西。 - TheBigC
1
@dewd 请检查 data 的定义。有一个换行符。我刚刚把它删除了。 - thefourtheye
7
你如何确定 _.values({id: 'medium', votes: 7}) 返回的是 ['medium', 7] 而不是 [7, 'medium']? - cipak
2
此解决方案不可靠,依赖于您对象中属性的顺序。 - Alex
显示剩余2条评论

8

这里是使用原生JS实现的:

var result = {};
[ { id: 'medium', votes: 7 },
  { id: 'low',    votes: 9 },
  { id: 'high',   votes: 5 } ].forEach(function(obj) {
    result[obj.id] = obj.votes;
});
console.log(result);

2
更简单的方式: each:
   var t = {};
   _.each(x, function(e){
     t[e.id] = e.votes;
   });
//--> {medium: 7, low: 9, high: 5}

1

Underscore中最强大的方法是reduce。你可以几乎做任何事情。而且更大的好处是你只需要遍历整个集合一次!

var array = [ 
    { id: 'medium', votes: 7 },
    { id: 'low',    votes: 9 },
    { id: 'high',   votes: 5 } 
];
var object = _.reduce(array, function(_object, item) { 
    _object[item.id] = item.votes; 
    return _object; 
}, {});

运行后,对象将会是:
{
  medium:7,
  low:9,
  high:5
}

在JavaScript中动态添加新属性到对象是一种反模式。https://richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html - Morio
明白了!那么,@morio,你有什么建议的解决方案? - Oscar Eduardo
嗯,你抓住我了。现在我想想,我不知道是否有避免这种情况的方法。我猜像 Lodash 这样的库内部也是这样做的。 - Morio

0

我知道这是一个旧帖子,但你可以使用_.reduce以一种简洁的方式进行转换

var data = [
    { id: 'medium', votes: 7 },
    { id: 'low',    votes: 9 },
    { id: 'high',   votes: 5 }
]

var output = _.reduce(data, function(memo, entry) {
    memo[entry.id] = entry.votes;
    return memo;
}, {});

console.log(output);

0

0
使用 indexBy。
_.indexBy([ 
   { id: 'medium', votes: 7 },
   { id: 'low',    votes: 9 },
   { id: 'high',   votes: 5 } 
 ], 'id');

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