You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP数组去重需求:保留用户4与各用户的最新单条聊天记录

问题分析与修复方案

你的问题根源完全在is_not_yet_in_array的判断逻辑上——它根本没搞懂「对话分组」的核心:对于当前用户ID=4来说,不管是4发给用户X,还是用户X发给4,这俩属于同一个对话,但你的条件只在判断「发送者相同」或者「接收者相同」,这既会错误地把不同对话的消息当成重复,又会漏掉同一对话的反向消息。

举个例子:当处理用户1发给4的消息时,你的函数会去结果数组里找有没有发送者是1或者接收者是4的消息吗?不对,你的逻辑是拿当前消息的发送者和结果里的发送者比、当前消息的接收者和结果里的接收者比,这完全没考虑「对话双方是4和X」这个最关键的分组依据。


正确的实现思路

要实现「保留用户4与每个用户的最新一条聊天记录」,我们可以换个更简洁可靠的方式:

  1. 给每个对话生成唯一标识:对于每条消息,找到与4对话的另一方ID(如果是4发给自己,另一方就是4)。
  2. 按时间倒序排序原始消息:确保最新的消息排在最前面。
  3. 用对话另一方ID作为数组键去重:遍历排序后的消息,把每条消息存入以「另一方ID」为键的数组中——因为同一个键只会保留最后一次赋值的内容,但由于我们先排了序,最新的消息会先被存入,后续同对话的旧消息不会覆盖它。
  4. 提取最终结果:把数组的值部分提取出来,就是我们需要的聊天列表。

修改后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 17:37:34