PHP数组去重需求:保留用户4与各用户的最新单条聊天记录
问题分析与修复方案
你的问题根源完全在is_not_yet_in_array的判断逻辑上——它根本没搞懂「对话分组」的核心:对于当前用户ID=4来说,不管是4发给用户X,还是用户X发给4,这俩属于同一个对话,但你的条件只在判断「发送者相同」或者「接收者相同」,这既会错误地把不同对话的消息当成重复,又会漏掉同一对话的反向消息。
举个例子:当处理用户1发给4的消息时,你的函数会去结果数组里找有没有发送者是1或者接收者是4的消息吗?不对,你的逻辑是拿当前消息的发送者和结果里的发送者比、当前消息的接收者和结果里的接收者比,这完全没考虑「对话双方是4和X」这个最关键的分组依据。
正确的实现思路
要实现「保留用户4与每个用户的最新一条聊天记录」,我们可以换个更简洁可靠的方式:
- 给每个对话生成唯一标识:对于每条消息,找到与4对话的另一方ID(如果是4发给自己,另一方就是4)。
- 按时间倒序排序原始消息:确保最新的消息排在最前面。
- 用对话另一方ID作为数组键去重:遍历排序后的消息,把每条消息存入以「另一方ID」为键的数组中——因为同一个键只会保留最后一次赋值的内容,但由于我们先排了序,最新的消息会先被存入,后续同对话的旧消息不会覆盖它。
- 提取最终结果:把数组的值部分提取出来,就是我们需要的聊天列表。
修改后的代码
function getLatestChatsPerUser($rawMessages, $currentUserId) { // 1. 先按消息时间倒序排序,确保最新的消息在最前面 usort($rawMessages, function($a, $b) { return strtotime($b['date']) - strtotime($a['date']); }); $uniqueChats = []; foreach ($rawMessages as $msg) { // 2. 找到当前对话的另一方ID $otherUserId = $msg['id_user_sending'] == $currentUserId ? $msg['id_user_receiving'] : $msg['id_user_sending']; // 3. 如果这个对话还没被存入,就添加进去(因为已经排序,第一个遇到的就是最新的) if (!isset($uniqueChats[$otherUserId])) { $uniqueChats[$otherUserId] = $msg; } } // 4. 提取数组的值,得到索引从0开始的最终聊天列表 return array_values($uniqueChats); } // 调用函数,当前用户ID是4 $arraytoconvertinJson = getLatestChatsPerUser($raw_message, 4);
为什么这个方案能解决你的问题?
- 分组逻辑正确:不管消息是4发出还是接收,只要对话另一方是同一个用户,就会被归为同一组,不会像原函数那样漏掉反向消息。
- 自动保留最新消息:因为先按时间倒序排序,所以每个对话分组里第一个被存入的就是最新的消息,后续同组的旧消息不会覆盖它。
- 代码更简洁高效:去掉了复杂的嵌套循环,用
usort和foreach实现,可读性和性能都更好。
测试你的原始数据
用你提供的原始消息数组测试,这个函数会返回:
- 与用户2的最新消息(
id_message=17/18,因为它们的时间最晚) - 与用户1的最新消息(
id_message=15) - 与用户3的最新消息(
id_message=11) - 如果有4发给自己的消息,也会保留最新的那一条
完全符合你期望的输出结果。
内容的提问来源于stack exchange,提问作者Reelbour
相关产品推荐
相关产品推荐

