Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
PHP递归实现扁平数组到树形结构的转换_创想鸟

PHP递归实现扁平数组到树形结构的转换

PHP递归实现扁平数组到树形结构的转换

本教程详细阐述如何使用PHP递归函数将包含父子关系的扁平化数组数据转换为嵌套的树形结构。文章将通过一个实际示例,深入解析递归算法的核心逻辑、常见错误修正及构建完整层级树的关键技巧,旨在帮助开发者高效地处理和展示具有层级关系的数据。

1. 引言:树形结构数据处理的挑战

在web开发中,处理具有层级关系的数据是一项常见任务,例如网站导航菜单、商品分类、评论回复、组织架构等。这类数据通常以扁平化的形式存储在数据库中,每条记录包含一个id和一个指向其父级记录的id(parentid)。然而,在前端展示或进行某些业务逻辑处理时,我们往往需要将这种扁平数据转换为嵌套的树形结构。

例如,我们可能有如下的扁平化数据:

$indexes = [    ['id' => 1, 'parentid' => 0, 'route' => 'root', 'title' => 'root'],    ['id' => 2, 'parentid' => 1, 'route' => 'parent', 'title' => 'parent'],    ['id' => 3, 'parentid' => 2, 'route' => 'child', 'title' => 'child']];

我们期望将其转换为如下的嵌套结构,其中子元素通过 pages 键包含:

$index = [  [    'id' => 1,    'pages' => [       [         'id' => 2,         'pages' => [          [            'id' => 3          ]        ]      ]    ]  ]];

2. 核心概念:递归

递归是一种函数或过程调用自身的编程技术。在处理树形结构数据时,递归表现出其天然的优势。构建树形结构的过程可以被分解为:找到当前父节点的所有直接子节点,然后对每个子节点重复相同的过程(即找到它们的子节点),直到没有更多的子节点为止。这正是递归思想的完美应用场景。

3. 构建树形结构的递归函数

我们将创建一个名为 buildSubs 的函数,它接收两个参数:完整的扁平化数据数组 $elms 和当前要查找的父ID $parentId。

立即学习“PHP免费学习笔记(深入)”;

3.1 函数逻辑解析

初始化分支数组: 在函数内部,首先初始化一个空数组 $branch,用于存放当前 $parentId 下的所有直接子元素。遍历所有元素: 遍历传入的 $elms 数组中的每一个元素 $elm。识别直接子元素: 检查当前元素 $elm 的 parentid 是否等于 $parentId。如果相等,则说明 $elm 是 $parentId 的一个直接子元素。递归构建子树: 如果 $elm 是直接子元素,则递归调用 buildSubs 函数,传入完整的 $elms 数组和当前子元素的 id ($elm[‘id’]) 作为新的 $parentId。这将返回当前子元素的所有后代组成的子树。挂载子树: 如果递归调用返回了子树(即 $children 不为空),则将其赋值给当前元素 $elm 的 pages 键。注意:这里是常见的错误点,必须是 $elm[‘pages’] = $children; 而不是 $elms[‘pages’] = $children;,因为我们是要修改当前正在处理的单个元素,而不是整个原始数组。添加到分支: 将处理好的 $elm(可能已经包含了其子树)添加到 $branch 数组中。返回分支: 循环结束后,返回 $branch 数组,它包含了 $parentId 下的所有直接子元素及其完整的子树。

3.2 初始调用与根节点处理

为了构建完整的树形结构,我们需要从根节点开始。在我们的示例数据中,根节点的 parentid 是 0。因此,在第一次调用 buildSubs 函数时,$parentId 应该设置为 0。

4. 完整示例代码

 $elm) { // 遍历所有元素        if ($elm['parentid'] == $parentId) { // 如果当前元素的parentid匹配目标parentId            // 递归调用自身,查找当前元素的子元素            $children = buildSubs($elms, $elm['id']);            // 如果存在子元素,则将其添加到当前元素的 'pages' 键中            if (!empty($children)) {                $elm['pages'] = $children; // 核心修正:修改 $elm 而非 $elms            }            // 将处理好的元素(可能已包含子树)添加到当前分支            $branch[] = $elm;            // 优化:从原数组中移除已处理的元素,减少后续遍历的范围 (可选,但对于大型数据集有性能优势)            // unset($elms[$key]); // 注意:如果使用此行,递归调用时需要传递引用或重新考虑逻辑        }    }    return $branch;}// 原始扁平化数据$indexes = [    ['id' => 1, 'parentid' => 0, 'route' => 'root', 'title' => 'root'],    ['id' => 2, 'parentid' => 1, 'route' => 'parent', 'title' => 'parent'],    ['id' => 3, 'parentid' => 2, 'route' => 'child', 'title' => 'child']];// 从根节点(parentid为0)开始构建完整的树$tree = buildSubs($indexes, 0);// 输出结果echo '
';var_dump($tree);echo '

';?>

5. 运行结果展示

执行上述代码后,var_dump($tree) 将输出以下结果,这正是我们期望的树形结构:

Array(    [0] => Array        (            [id] => 1            [parentid] => 0            [route] => root            [title] => root            [pages] => Array                (                    [0] => Array                        (                            [id] => 2                            [parentid] => 1                            [route] => parent                            [title] => parent                            [pages] => Array                                (                                    [0] => Array                                        (                                            [id] => 3                                            [parentid] => 2                                            [route] => child                                            [title] => child                                        )                                )                        )                )        ))

6. 注意事项与最佳实践

性能考量: 对于非常庞大或层级非常深的数据集,递归可能会导致性能问题(如栈溢出或多次重复遍历)。在这种情况下,可以考虑使用迭代方法(如基于引用的方法)或在数据库层面进行优化查询。内存消耗: 深度嵌套的数组结构会占用更多内存。确保您的服务器配置能够处理预期的数据量。灵活性: 为了使函数更通用,可以将其参数化,允许用户指定ID键名、父ID键名和子数组键名(例如:'id_key', 'parent_id_key', 'children_key')。错误处理:循环引用: 如果数据中存在A是B的父,B是A的父的循环引用,递归函数将陷入无限循环。在实际应用中,应避免此类数据结构或在递归中加入深度限制或已访问节点记录。孤儿节点: 如果某个元素的 parentid 指向一个不存在的ID,它将不会被包含在任何分支中,除非您有特定的逻辑来处理这些“孤儿”节点。优化遍历: 在 foreach 循环内部,如果找到并处理了一个元素,可以考虑从原始 $elms 数组中将其移除(使用 unset($elms[$key]))。这样可以减少后续迭代的元素数量,从而提高效率。但请注意,如果这样做,递归调用时需要确保 $elms 数组的副本或引用传递方式是正确的。上述示例代码为了简洁和避免潜在的引用复杂性,并未采用此优化。

7. 总结

通过本教程,我们学习了如何利用PHP的递归功能将扁平化的父子关系数据转换为易于处理和展示的树形结构。理解递归的核心逻辑、正确处理当前元素的修改以及从正确的根节点开始构建是实现这一转换的关键。虽然递归在处理树形数据时非常优雅,但在面对大规模数据时也需要考虑其性能和内存影响,并根据实际需求选择最合适的实现方案。

以上就是PHP递归实现扁平数组到树形结构的转换的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1266314.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
解决Laravel分页:理解Builder与Paginator实例的转换
上一篇 2025年12月10日 09:34:26
如何解决MacOS PHP版本冲突问题 Mac环境中PHP切换与兼容建议
下一篇 2025年12月10日 09:34:38

相关推荐

  • iphone15promax怎么清理缓存?

    如何清理iPhone 15 Pro Max的缓存? 1、进入手机设置界面,选择【通用】选项。 2、点击进入【iPhone储存空间】。 3、在列表中查看各个应用所占用的存储情况,找到占用较大的应用后,逐个进入应用进行缓存清理。 关闭iCloud云盘的操作步骤: 1、在设置界面中点击顶部的【Apple …

    2026年9月23日
    000
  • Django运行migrate报错“django.db.utils.OperationalError”:如何解决SSL连接错误?

    django运行migrate报错“django.db.utils.operationalerror”的解决方法 在使用django项目的过程中,有时候在命令行中运行“python manage.py migrate”命令时会遇到“django.db.utils.operationalerror”的…

    2026年9月23日
    000
  • LINUX下如何安装输入法_LINUX安装中文输入法(搜狗/Fcitx)教程

    首先安装Fcitx输入法框架并切换默认输入法为Fcitx,接着添加中文语言支持并配置区域选项,然后下载并安装搜狗输入法Linux版,再通过启动应用程序设置Fcitx随系统自启,最后重启会话并在Fcitx配置中添加搜狗拼音输入法。 如果您在使用Linux系统时需要输入中文,但默认环境下缺少可用的中文输…

    2026年9月23日
    100
  • Deepseek 满血版联动 Typinator Pro,创建复杂文本模板​

    Deepseek 满血版联动 Typinator Pro,创建复杂文本模板​Deepseek 满血版联动 Typinator Pro,创建复杂文本模板​Deepseek 满血版联动 Typinator Pro,创建复杂文本模板​Deepseek 满血版联动 Typinator Pro,创建复杂文本模板​

    将 ai 与 typinator 联动可打造高效文本模板系统。1. 使用 deepseek 等 ai 工具生成结构化内容,如邮件草稿;2. 将生成内容调整为 typinator 变量格式(如 %|name%);3. 导入 typinator 并设置快捷短语,实现一键插入。典型场景包括批量写邮件、报告…

    2026年9月23日 • 用户投稿
    000
  • 总结laravel中JSON格式的转换方法

    laravel 是一款流行的 php web 开发框架,它提供了很多开箱即用的功能,包括对 json 数据的支持。本文将介绍如何在 laravel 中转换 json。 JSON 简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于 JavaScri…

    用户投稿 2026年9月23日
    100
  • Vscode怎么批量修改变量?Vscode变量重命名操作指南

    Vscode怎么批量修改变量?Vscode变量重命名操作指南Vscode怎么批量修改变量?Vscode变量重命名操作指南Vscode怎么批量修改变量?Vscode变量重命名操作指南Vscode怎么批量修改变量?Vscode变量重命名操作指南

    vscode批量修改变量的方法是选中变量按f2输入新名回车,但要更精确控制重命名范围可采取以下措施:1.使用“查找和替换”功能(ctrl+h),结合正则表达式限定匹配范围;2.使用语言支持的“重构”功能(右键→重构→重命名),基于语义分析避免误改;3.安装增强重命名插件提升功能;4.利用静态代码分析…

    2026年9月23日 • 用户投稿
    000
  • Java中用户输入验证:正确使用equals()或转换为整数进行比较

    本教程详细阐述了Java中用户输入字符串(如菜单选项)验证的正确方法。针对==运算符在字符串比较中的局限性,文章介绍了两种解决方案:一是使用String.equals()方法进行内容比较,二是将字符串输入解析为整数后进行数值比较。通过代码示例,帮助开发者避免常见的字符串比较错误,确保程序逻辑的健壮性…

    2026年9月23日
    000
  • Redis缓存数据一致性难题:如何兼顾效率和一致性?

    Redis缓存数据一致性难题:如何解决? 在使用Redis作为缓存时,维护数据一致性至关重要。特别是对于频繁更新的数据,如使用Redis缓存的listUser结果集,如何确保在执行插入、更新或删除操作后,缓存中的结果依然是最新的? 针对此难题,有人提出在执行这些操作后立即清空缓存。然而,当操作过于频…

    2026年9月23日
    000
  • 空洞骑士丝之歌可以联机吗 联机功能情况说明​

    空洞骑士丝之歌目前无法进行联机游戏,尽管官方尚未正式声明,但游戏中并未设置多人在线模式或服务器支持功能。同时,剧情发展、地图结构等内容均围绕主角大黄蜂独立构建,未提供其他可操作角色,因此不具备联机游玩的基础条件。 关于空洞骑士丝之歌是否支持联机的详细说明如下: 一、当前联机状态明确 截至目前,本作不…

    2026年9月23日
    000
  • 一文探讨Laravel的启动过程

    laravel是一个开源的php框架,它被广泛用来开发大型的web应用程序。laravel为开发人员提供了高度可扩展性、高度优化的工具,以及强大的路由和验证功能,可以让开发者快速地构建出复杂的web应用程序。本文将探讨laravel的启动过程,以帮助初学者更好地理解这个框架。 理解Laravel框架…

    用户投稿 2026年9月23日
    100
  • 微软免费文件恢复工具介绍

    微软免费文件恢复工具介绍微软免费文件恢复工具介绍微软免费文件恢复工具介绍微软免费文件恢复工具介绍

    现在好了,最近微软在 windows 10 应用商店中上架了一款免费的数据删除恢复工具 windows file recovery,猿妹再也不用担心误删文件了。 Windows File Recovery基于命令行程序设计,大小仅有8.26MB,所有Windows 10用户均可免费下载使用。 无论是…

    2026年9月23日 • 用户投稿
    000
  • 淘宝评价显示延迟怎么办 淘宝评价刷新与修复技巧

    先检查网络与应用状态,确认手机网络稳定并清理淘宝App缓存,避免因本地问题导致评价加载延迟。 淘宝评价显示延迟,通常不会持续太久,但确实会影响购物决策。核心是先判断是局部问题还是普遍现象,然后针对性地处理。 检查网络与应用状态 评价加载不出来,大概率是本地环境的问题。先确认你的手机网络是否稳定,可以…

    2026年9月23日
    000
  • VSCode精简配置Perl:语法检查、中文编码、正则调试

    vscode中perl语法检查不生效的主要原因是perl解释器路径未正确配置或缺失,解决方法是在settings.json中明确设置”perl.perlpath”指向正确的perl可执行文件;其次是因缺少cpan模块导致检查失败,需安装对应模块;此外,多个perl扩展冲突、大…

    2026年9月23日
    000
  • 抖音小程序自动续费怎么关闭?抖音小程序扣费如何取消

    随着抖音小程序在日常生活中的广泛应用,其自动续费功能也引发了不少用户的关注。不少人在不知情的情况下被扣费,因此了解如何关闭该功能显得尤为重要。本文将为您详细介绍关闭抖音小程序自动续费的操作流程,助您远离不必要的消费。 一、什么是抖音小程序自动续费 所谓抖音小程序自动续费,是指用户在购买某项服务后,系…

    2026年9月23日
    000
  • vivo X300 系列发布 2 亿像素+天玑 9500 4399 元起售

    vivo X300 系列发布 2 亿像素+天玑 9500 4399 元起售vivo X300 系列发布 2 亿像素+天玑 9500 4399 元起售vivo X300 系列发布 2 亿像素+天玑 9500 4399 元起售vivo X300 系列发布 2 亿像素+天玑 9500 4399 元起售

    10 月 13 日晚间 19:00,vivo 正式召开新品发布会,推出全新年度影像旗舰 x300 系列,首发包含 vivo x300 与 vivo x300 pro 两款机型。 本代 X300 系列的核心亮点聚焦于影像系统的全面突破。标准版 vivo X300 搭载了 2 亿像素主摄,配备 1/1.…

    2026年9月23日 • 用户投稿
    000
  • Yandex对俄贸易专用搜索 官方网站入口一键直达

    Yandex对俄贸易专用搜索官网为https://yandex.com/,提供俄语内容索引、企业信息查找、地图定位及自动翻译等功能,支持跨境业务拓展与市场分析。 Yandex对俄贸易专用搜索官方网站入口在哪里?这是不少网友都关注的,接下来由PHP小编为大家带来Yandex对俄贸易专用搜索官方网站入口…

    2026年9月23日
    300
  • AO3镜像站直接访问链接_AO3镜像站推荐镜像站点

    AO3镜像站直接访问链接包括https://archiveofourown.org/、https://ao3.cubeart.club/、https://l.ao4.live、https://s.ao3l.live,用户可通过浏览器直接输入网址访问,主站无法加载时可切换镜像站点,部分支持手机浏览且无…

    2026年9月23日
    000
  • AfterEffects如何制作AI动效视频?创建动态AI视频的完整教程

    AfterEffects如何制作AI动效视频?创建动态AI视频的完整教程AfterEffects如何制作AI动效视频?创建动态AI视频的完整教程AfterEffects如何制作AI动效视频?创建动态AI视频的完整教程AfterEffects如何制作AI动效视频?创建动态AI视频的完整教程

    答案是掌握AE动画原理并融合AI素材进行创作。需根据风格选择合适AI工具(如Midjourney、RunwayML),注重素材质量、可定制性与透明背景支持;将AI素材导入AE后,调整分辨率,运用颜色校正、模糊、跟踪及表达式增强效果;通过关键帧控制位置、缩放、旋转,并应用缓动实现流畅动画;搭配契合主题…

    2026年9月23日 • 用户投稿
    200
  • 如何在Java中安装Eclipse开发环境

    先安装JDK并配置环境变量,再下载安装Eclipse IDE。1. 安装JDK:从Oracle或Eclipse Adoptium下载JDK 17/21,按提示安装,设置JAVA_HOME和PATH,用java -version验证。2. 安装Eclipse:官网下载“Eclipse IDE for …

    2026年9月23日
    000
  • 配置Linux下vim自动缩进

    从终端打开配置文件: vim ~/.vimrc 添加如下代码: set tabstop=4set softtabstop=4set shiftwidth=4set autoindentset cindentset cinoptions={0,1s,t0,n-2,p2s,(03s,=.5s,>1…

    2026年9月23日
    800

发表回复

登录后才能评论
关注微信