我想将一组中的2个人之间的所有邮件分组(聊天)。如果我是作者或接收者,那无关紧要。
让我们说一下这个示例代码。
const messages = [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
]
想象一下,我是用户ID = 1,所以我想得到这个:
const chats = [
{
chatName: 'Name of user ID 2', messages: [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
]
},
{
chatName: 'Name of user ID 3', messages: [
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
]
}
];
如何使用Lodash实现这一目标?
答案 0 :(得分:1)
不确定lodash,但您可以使用普通js - reduce
和map
来获取该结构
const messages = [{
id: '100',
text: 'aaa',
author: {
id: '1'
},
receiver: {
id: '2'
}
},
{
id: '101',
text: 'bbb',
author: {
id: '2'
},
receiver: {
id: '1'
}
},
{
id: '102',
text: 'ccc',
author: {
id: '3'
},
receiver: {
id: '1'
}
},
];
function groupByPair(arr) {
return [
...arr.reduce((a, b) => {
let {
author,
receiver
} = b;
let s = [author.id, receiver.id].sort().join('-');
a.set(s, a.has(s) ? a.get(s).concat(b) : [b]);
return a;
}, new Map)
].map(e => ({
chatName: 'Name of user ID ' + e[0].substring(e[0].indexOf('-') + 1),
messages: e[1]
}));
}
console.log(groupByPair(messages));
答案 1 :(得分:1)
使用Lodash或Underscore.js:
var grouped = _.groupBy(messages, m => _.sortBy([m.author.id, m.receiver.id]));
var formatted = _.map(grouped, (v, name) => ({ chatname: name, messages: v }));
你可以将它们组合成一条线,但这对我来说似乎过于密集。
我冒昧地定义了一个更复杂的测试数据集,以确保边缘案例得到更好的覆盖:
var messages = [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
{ id: '103', text: 'zzz', author: { id: '2' }, receiver: { id: '1' } },
{ id: '104', text: 'yyy', author: { id: '3' }, receiver: { id: '4' } },
{ id: '105', text: 'xxx', author: { id: '3' }, receiver: { id: '1' } }
使用此数据,上面的代码产生formatted
:
[
{ chatname: '1,2',
messages: [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '103', text: 'zzz', author: { id: '2' }, receiver: { id: '1' } }
]
},
{ chatname: '1,3', messages: [
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
{ id: '105', text: 'xxx', author: { id: '3' }, receiver: { id: '1' } }
]
},
{ chatname: '3,4', messages: [
{ id: '104', text: 'yyy', author: { id: '3' }, receiver: { id: '4' } }
]
}
]
与所需输出的主要区别在于chatname
值。我没看到你是如何命名的,所以我坚持使用Lodash / Underscore的原生groupby
键。
答案 2 :(得分:0)
您可以使用_.groupby
执行此操作。我首先过滤数组,以便只留下涉及用户1的消息。
const messages = [
{ id: '100', text: 'aaa', author: { id: '1' }, receiver: { id: '2' } },
{ id: '101', text: 'bbb', author: { id: '2' }, receiver: { id: '1' } },
{ id: '102', text: 'ccc', author: { id: '3' }, receiver: { id: '1' } },
];
const filtered = messages.filter((msg) => {
return msg.author.id === '1' || msg.receiver.id === '1'
});
const groups = _.groupBy(filtered, (msg) => {
return msg.author.id === '1' ? msg.receiver.id : msg.author.id
});
console.log(groups);
<script src="https://unpkg.com/lodash@4.17.4"></script>