使用lodash中的键值合并一个对象数组?

我使用node.js和lodash。

我有这样的数据:

[ { to: [ 'foo@bar.com', 'foo1@bar.com' ], submittedSubs: [ [Object] ] }, { to: [ 'foo@bar.com', 'foo2@bar.com' ], submittedSubs: [ [Object], [Object], [Object] ] } ] 

我想把它变成这样的数据,它被“sorting” to

 [ { to: 'foo@bar.com', submittedSubs: [ [Object],[Object], [Object], [Object] ] }, { to: 'foo1@bar.com', submittedSubs: [ [Object] ] }, { to: 'foo2@bar.com', submittedSubs: [ [Object], [Object], [Object] ] } ] 

我怎样才能做到这一点?

我试过这个:

 spam[0].to.push('foo@bar.com'); spam[0].to.push('foo1@bar.com'); spam[1].to.push('foo@bar.com'); spam[1].to.push('foo2@bar.com'); console.log('data is',spam); var byUser=[]; _.each(spam, function(data){ _.each(data.to,function(addr){ byUser.push({to:addr,submittedSubs:data.submittedSubs}); }); }); console.log('attempt',_.merge(byUser)); 

但是这给了我这个:

 [ { to: 'foo@bar.com', submittedSubs: [ [Object] ] }, { to: 'foo1@bar.com', submittedSubs: [ [Object] ] }, { to: 'foo@bar.com', submittedSubs: [ [Object], [Object], [Object] ] }, { to: 'foo2@bar.com', submittedSubs: [ [Object], [Object], [Object] ] } ] 

这会为你工作:

 var unique = {}; byUser.forEach(function(user) { unique[user.to] = unique[user.to] || []; unique[user.to] = unique[user.to].concat(user.submittedSubs); }); unique = Object.keys(unique).map(function (key, i) { return {to: key, submittedSubs: unique[key]}; }); /* [ { to: 'foo@bar.com', submittedSubs: [ [Object] ] }, { to: 'foo1@bar.com', submittedSubs: [ [Object] ] }, { to: 'foo2@bar.com', submittedSubs: [ [Object], [Object], [Object], [Object] ] } ] */ 

_.uniq ,这应该是可以实现使用_.uniq的callbackfunction,但我不能让你的工作方式,你需要它。

你应该可以在最后一个数组中使用_.uniq的_.uniq :

 _.uniq(byUser, "to"); /* [ { to: 'foo@bar.com', submittedSubs: [ [Object] ] }, { to: 'foo1@bar.com', submittedSubs: [ [Object] ] }, { to: 'foo2@bar.com', submittedSubs: [ [Object], [Object], [Object] ] } ] */ 

我想有一些不错的lodash设施可以缩短这一点,但这里是一个vanilla-js解决scheme:

 var data = [ { to: [ 'foo@bar.com', 'foo1@bar.com' ], submittedSubs: [{ id: 'sub1' }] }, { to: [ 'foo@bar.com', 'foo2@bar.com' ], submittedSubs: [{ id: 'sub2' }, { id: 'sub3' }, { id: 'sub4' }] } ]; var emailSubsMap = data.reduce(function(result, record) { record.to.forEach(function(email) { result[email] = (result[email] || []) .concat(record.submittedSubs); }); return result; }, {}); var formatted = Object.keys(emailSubsMap).map(function(email) { return { to: email, submittedSubs: emailSubsMap[email] }; }).sort(function(a, b) { return a.to <= b.to ? -1 : 1; }); console.log(JSON.stringify(formatted)); 

(格式化)控制台输出:

 [ { "to": "foo1@bar.com", "submittedSubs": [ { "id": "sub1" } ] }, { "to": "foo2@bar.com", "submittedSubs": [ { "id": "sub2" }, { "id": "sub3" }, { "id": "sub4" } ] }, { "to": "foo@bar.com", "submittedSubs": [ { "id": "sub1" }, { "id": "sub2" }, { "id": "sub3" }, { "id": "sub4" } ] } ] 

请注意,我只是为了testing的目的而嘲笑submitSubs对象的外观。

JSFiddle示例

一些关于sorting的注意事项:

  • 我的第一个版本没有正确sorting…它已被更新。 🙂
  • 您请求的sorting方法不遵循JavaScript的“本地”stringsorting顺序。 例如, ['foo@bar.com', 'foo2@bar.com', 'foo1@bar.com'].sort() --> ['foo1@bar.com','foo2@bar.com','foo@bar.com'] ,所以如果你真的想要foo@bar.comfoo1@bar.com之前,你需要更详细地定义你的sorting标准。