在 lodash 中使用键值合并对象数组?
Merge an array of objects using key value in lodash?
我正在使用 node.js 和 lodash。
我有这样的数据:
[
{
to: [ 'foo@bar.com', 'foo1@bar.com' ],
submittedSubs: [ [Object] ]
},
{
to: [ 'foo@bar.com', 'foo2@bar.com' ],
submittedSubs: [ [Object], [Object], [Object] ]
}
]
我想把它变成像这样的数据 "sorted" 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
from lodash:
_.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 解决方案:
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" }
]
}
]
请注意,我只是为了测试目的模拟了 submittedSubs
对象的样子。
关于排序的几点说明:
- 我的第一个版本排序不正确...已更新。 :)
- 您请求的排序方法不符合 JavaScript 的 "native" 字符串排序顺序。例如,
['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
之前,您需要更详细地定义您的排序标准。
我正在使用 node.js 和 lodash。
我有这样的数据:
[
{
to: [ 'foo@bar.com', 'foo1@bar.com' ],
submittedSubs: [ [Object] ]
},
{
to: [ 'foo@bar.com', 'foo2@bar.com' ],
submittedSubs: [ [Object], [Object], [Object] ]
}
]
我想把它变成像这样的数据 "sorted" 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
from lodash:
_.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 解决方案:
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" }
]
}
]
请注意,我只是为了测试目的模拟了 submittedSubs
对象的样子。
关于排序的几点说明:
- 我的第一个版本排序不正确...已更新。 :)
- 您请求的排序方法不符合 JavaScript 的 "native" 字符串排序顺序。例如,
['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
之前,您需要更详细地定义您的排序标准。