如何在JavaScript数组中去重对象属性并保留用户最新消息
解决方案:过滤消息数组,保留每个用户的最新消息
我来帮你搞定这个需求!要实现每个对话用户只保留最新一条消息的效果,我们可以通过几个简单的步骤来实现,这里提供两种实用的方案:
方案一:分步处理(清晰易懂)
适合需要中间步骤做额外处理的场景,逻辑一目了然:
步骤拆解
- 标记每条消息的对话对象:先给每条消息添加对方用户的ID和名称,避免后续重复判断自己是发送方还是接收方。
- 按时间倒序排序:利用MongoDB
_id的特性(包含时间戳,字符串可直接比较先后),把最新消息排到最前面。 - 去重保留最新:用集合记录已经处理过的用户,只保留每个用户的第一条(也就是最新的)消息。
代码示例
// 先定义你的用户ID(从示例消息里提取的) const myUserId = "5f004feae528a90017327f3b"; const originalMessages = [/* 你的原始消息数组 */]; // 1. 给每条消息添加对话对象的信息 const messagesWithContact = originalMessages.map(msg => { const amISender = msg.sender === myUserId; return { ...msg, contactId: amISender ? msg.receiver : msg.sender, contactName: amISender ? msg.receiverInfo.name : msg.senderInfo.name }; }); // 2. 按消息时间倒序排序(新消息在前) const sortedMessages = messagesWithContact.sort((a, b) => { return b._id.localeCompare(a._id); }); // 3. 去重,保留每个用户的最新消息 const seenContacts = new Set(); const filteredMessages = sortedMessages.filter(msg => { if (!seenContacts.has(msg.contactId)) { seenContacts.add(msg.contactId); return true; } return false; }); console.log(filteredMessages);
方案二:简洁版(高效紧凑)
如果不需要中间步骤,用reduce可以更高效地完成,代码更紧凑:
代码示例
const myUserId = "5f004feae528a90017327f3b"; const originalMessages = [/* 你的原始消息数组 */]; const filteredMessages = Object.values( originalMessages.reduce((acc, currentMsg) => { // 获取当前消息的对话用户ID const contactId = currentMsg.sender === myUserId ? currentMsg.receiver : currentMsg.sender; // 若该用户还没记录,或当前消息比已存的更新,就替换 if (!acc[contactId] || currentMsg._id.localeCompare(acc[contactId]._id) > 0) { acc[contactId] = currentMsg; } return acc; }, {}) ); console.log(filteredMessages);
额外说明
- 如果你的消息不是用MongoDB的
_id来标识时间,而是有单独的timestamp字段,只需要把currentMsg._id.localeCompare(...)换成currentMsg.timestamp > acc[contactId].timestamp即可。 - 示例里的用户名称有轻微不一致(比如"Me"、"ME"),如果需要统一格式,可以在添加
contactName时做处理,比如amISender ? msg.receiverInfo.name.trim().toLowerCase() : ...。
内容的提问来源于stack exchange,提问作者Similoluwa Odeyemi
相关产品推荐
相关产品推荐

