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

如何移除不同数组维度间的重复数据?基于自关联导航菜单场景

解决自关联导航菜单多维数组的去重问题

看起来你是在处理树形结构的导航菜单数据,用Eloquent预加载子节点后得到了嵌套数组,现在需要清理掉不同层级里的重复项对吧?我来给你几个可行的方案:

一、从数据库查询层面避免重复(推荐)

如果重复数据是因为查询逻辑导致的(比如某些子节点被意外多次加载),可以先从根源上解决:

  1. 确保关联定义正确
    你的childs关联应该是这样的(在App\Menu模型里):

    public function childs()
    {
        return $this->hasMany(Menu::class, 'id_parent', 'id')->distinct();
    }
    

    这里加上distinct()可以确保每个子节点只被查询一次,避免因为关联关系导致的重复加载。

  2. 查询时添加唯一约束
    如果你的重复是指同一个id的菜单出现在不同层级(比如某个菜单既是顶级又是子菜单),可以在查询时过滤掉重复的id:

    $menus = App\Menu::with(['childs' => function ($query) {
        $query->distinct();
    }])->get()->unique('id');
    

    unique('id')会在顶级集合里去重,但子节点里的重复还需要递归处理,所以接下来看数组层面的方案。

二、数组层面递归去重(处理嵌套结构的重复)

如果数据库层面没法完全避免,或者你需要基于url等其他字段去重,可以写一个递归函数来遍历整个嵌套数组,记录已经出现过的标识(比如id或url),然后移除重复项:

示例代码(基于id去重)

function removeDuplicateMenus($menus, &$seenIds = []) {
    $uniqueMenus = [];
    foreach ($menus as $menu) {
        // 如果当前菜单id已经见过,跳过
        if (in_array($menu['id'], $seenIds)) {
            continue;
        }
        $seenIds[] = $menu['id'];
        // 递归处理子菜单
        if (!empty($menu['childs'])) {
            $menu['childs'] = removeDuplicateMenus($menu['childs'], $seenIds);
        }
        $uniqueMenus[] = $menu;
    }
    return $uniqueMenus;
}

// 使用方法
$originalMenus = App\Menu::with(['childs'])->get()->toArray();
$uniqueMenus = removeDuplicateMenus($originalMenus);

基于url去重的调整

如果你的重复判断依据是url而不是id,只需要把上面的$menu['id']换成$menu['url'],$seenIds改成$seenUrls即可:

function removeDuplicateMenusByUrl($menus, &$seenUrls = []) {
    $uniqueMenus = [];
    foreach ($menus as $menu) {
        if (in_array($menu['url'], $seenUrls)) {
            continue;
        }
        $seenUrls[] = $menu['url'];
        if (!empty($menu['childs'])) {
            $menu['childs'] = removeDuplicateMenusByUrl($menu['childs'], $seenUrls);
        }
        $uniqueMenus[] = $menu;
    }
    return $uniqueMenus;
}

三、额外提示

  • 如果你用的是Laravel的集合,也可以利用集合的递归方法来处理,比如flatMap结合unique,但嵌套结构下递归函数更直观。
  • 最好先排查为什么会出现重复数据:是数据库里本身有重复的记录?还是关联查询的逻辑问题?从根源解决会更高效。

内容的提问来源于stack exchange,提问作者Hula Hula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:35:35