使用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.com
来foo1@bar.com
之前,你需要更详细地定义你的sorting标准。