首页 > 编程语言 >php优化递归算法优化

php优化递归算法优化

时间:2023-08-08 10:45:54浏览次数:27  
标签:递归 parent permission parentKey utf8mb4 children php 优化 id

2023年8月7日13:59:31

因为最近开发自己的一些常用系统,所以为了自由度较高一点,经常分类都是无限层级,所以递归用的比较多,但是发现当分类大于三层,数据1万以上递归就会很慢,所以一直在寻求优化算法,使用使用chagpt优化的算法,基本无法使用,后续想到用php原生函数来使用,结果性能飙升

数据库结构:

CREATE TABLE `admin_permission` (
 `id` bigint unsigned NOT NULL AUTO_INCREMENT,
 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
 `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
 `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
 `is_delete` tinyint(1) NOT NULL DEFAULT '10' COMMENT '10默认99删除',
 `parent_permission_id` int unsigned NOT NULL DEFAULT '0' COMMENT '父ID 0是顶级',
 `permission_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '控制名称',
 `permission_url` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '前台控制器URL',
 `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '组件名称',
 `backstage_permission_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '后台权限URL',
 `tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '标签,标志',
 `is_menu` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '作为菜单显示,1是,2不是',
 `small_icon_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'pc端图标',
 `redirect` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '跳转页面',
 `component` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '组件类型',
 `keep_alive` tinyint NOT NULL DEFAULT '1' COMMENT '是否keep_alive',
 `hidden` tinyint(1) DEFAULT '10' COMMENT '菜单是否显示10显示20不显示',
 PRIMARY KEY (`id`),
 KEY `parent_permission_id` (`parent_permission_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14384 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='管理员权限表';

生产测试数据:,随便自己插入几条数据,然后使用下面的方法在第三层生成测试数据

$list = AdminPermission::orderBy('id', 'asc')->get()->toArray();
        $array = self::treeMenu($list, 0, 'parent_permission_id');

//        pp($array);
       // 制造10000+的测试数据,测试算法姓名
        foreach ($array as $k => &$v) {
            if (!empty($v['children'])) {
                foreach ($v['children'] as $kk => &$vv) {
                    if (!empty($vv['children'])) {
                        foreach ($vv['children'] as $kkk => &$vvv) {

                            unset($vvv['label']);
                            unset($vvv['id']);
                            for ($i = 1; $i <= 100; $i++) {
                                DB::table('admin_permission')->insert($vvv);
                            }
                        }
                    }
                }
            }
        }

php实现

    //递归数据
    public static function treeMenu(array $menu = [], int $parent = 0, string $parentKey = 'parent_id')
    {
        $tree = array();
        foreach ($menu as $v) {
            if ($v[$parentKey] == $parent) {
                $v['children'] = self::treeMenu($menu, $v['id'], $parentKey);
                if (empty($v['children'])) {
                    unset($v['children']);
                }
                $tree[] = $v;
            }
        }
        return $tree;
    }

使用php原生函数实现的,默认三层搜索

$tree = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
            return $permission[$parentKey] == $parent_id;
        });
        if (!empty($tree)) {
            foreach ($tree as &$v) {

                $parent_id = $v['id'];
                $v['children'] = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
                    return $permission[$parentKey] == $parent_id;
                });

                if (!empty($v['children'])) {
                    foreach ($v['children'] as &$vv) {

                        $parent_id = $vv['id'];
                        $vv['children'] = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
                            return $permission[$parentKey] == $parent_id;
                        });

//                        if (!empty($vv['children'])) {
//                            foreach ($vv['children'] as &$vvv) {
//
//                                $parent_id = $vvv['id'];
//                                $vvv['children'] = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
//                                    return $permission[$parentKey] == $parent_id;
//                                });
//                            }
//                        }
                    }
                }
            }
        }

测试:

1,php实现方法测试:

第一次:
待递归总数--:14350
开始时间:2023-08-08 10:28:22
结束时间:2023-08-08 10:28:28

第二次:
待递归总数--:14350
开始时间:2023-08-08 10:29:04
结束时间:2023-08-08 10:29:09

2,php原生实现方法测试:

第一次:
待递归总数--:14350
开始时间:2023-08-08 10:30:46
结束时间:2023-08-08 10:30:46

第二次:
待递归总数--:14350
开始时间:2023-08-08 10:31:00
结束时间:2023-08-08 10:31:01

完整代码:

public function index(Request $request)
    {
        $list = AdminPermission::orderBy('id', 'asc')->get()->toArray();
        $array = self::treeMenu($list, 0, 'parent_permission_id');

//        pp($array);
       // 制造10000+的测试数据,测试算法姓名
        foreach ($array as $k => &$v) {
            if (!empty($v['children'])) {
                foreach ($v['children'] as $kk => &$vv) {
                    if (!empty($vv['children'])) {
                        foreach ($vv['children'] as $kkk => &$vvv) {

                            unset($vvv['label']);
                            unset($vvv['id']);
                            for ($i = 1; $i <= 100; $i++) {
                                DB::table('admin_permission')->insert($vvv);
                            }
                        }
                    }
                }
            }
        }
//die;

        $count = AdminPermission::orderBy('id', 'asc')->get()->count();
        p('待递归总数--:' . $count);

        $list = AdminPermission::orderBy('id', 'asc')->get(['id', 'parent_permission_id', 'permission_name'])->toArray();

        //php代码实现递归
        p('开始时间:' . date('Y-m-d H:i:s'));
        $rr = self::treeMenu($list, 0, 'parent_permission_id');
        p('结束时间:' . date('Y-m-d H:i:s'));

        //php原生函数实现递归 
        p('开始时间:' . date('Y-m-d H:i:s'));
        $parent_id = 0;
        $parentKey = 'parent_permission_id';

        $tree = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
            return $permission[$parentKey] == $parent_id;
        });
        if (!empty($tree)) {
            foreach ($tree as &$v) {

                $parent_id = $v['id'];
                $v['children'] = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
                    return $permission[$parentKey] == $parent_id;
                });

                if (!empty($v['children'])) {
                    foreach ($v['children'] as &$vv) {

                        $parent_id = $vv['id'];
                        $vv['children'] = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
                            return $permission[$parentKey] == $parent_id;
                        });

//                        if (!empty($vv['children'])) {
//                            foreach ($vv['children'] as &$vvv) {
//
//                                $parent_id = $vvv['id'];
//                                $vvv['children'] = array_filter($list, function ($permission) use ($parent_id, $parentKey) {
//                                    return $permission[$parentKey] == $parent_id;
//                                });
//                            }
//                        }
                    }
                }
            }
        }
        p('结束时间:' . date('Y-m-d H:i:s'));
        pp($tree);
    }

    //递归数据
    public static function treeMenu(array $menu = [], int $parent = 0, string $parentKey = 'parent_id')
    {
        $tree = array();
        foreach ($menu as $v) {
            if ($v[$parentKey] == $parent) {
                $v['children'] = self::treeMenu($menu, $v['id'], $parentKey);
                if (empty($v['children'])) {
                    unset($v['children']);
                }
                $tree[] = $v;
            }
        }
        return $tree;
    }

标签:递归,parent,permission,parentKey,utf8mb4,children,php,优化,id
From: https://www.cnblogs.com/zx-admin/p/17611278.html

相关文章

  • linux 如何创建php文件
    首先,需要先安装PHP。在Linux中,你可以通过使用命令行工具来安装PHP。具体方法如下: sudoapt-getupdatesudoapt-getinstallphp以上命令会自动安装PHP并将其设置为默认选项。一旦你安装好了PHP,你就可以开始创建PHP文件了。在Linux中,你可以使用任何文本编辑器来创建PHP文件......
  • No input file specified. thinkphp 高版本正则重写问题
    Noinputfilespecified.问题描述:使用TP框架做项目时,在启用REWRITE的伪静态功能的时候,首页可以访问,但是访问其它页面的时候,就提示:“Noinputfilespecified.”原因在于使用的PHP5.6是fast_cgi模式,而在某些情况下,不能正确识别path_info所造成的错误默认的.htaccess里面的规则:......
  • 递归遍历QTreeView+QStandrdItemModel
    //递归遍历点击查看代码voiditerateTreeViewNodes(constQModelIndex&parentIndex,QStandardItemModel*model,QVector<QStandardItem*>&items){ introwCount=model->rowCount(parentIndex); intcolumnCount=model->columnCount(parentIndex); ......
  • Vue3 路由优化,使页面初次渲染效率翻倍
    3996条路由?addRoute函数用了大约1s才执行完毕。通过观察,发现居然有3996条路由记录。可是项目并没有这么多的页面啊~重复路由letroutes:Array<RouteRecordRaw>=[{path:'/promotion/ticket-list-jegotrip',component:()=>import(/*webp......
  • MySQL插入1000万条数据,用PHP如何做才能保证性能的最优
    插入大量数据时,确保性能最优是很重要的。下面是几种在PHP中快速向MySQL插入大量数据的优化方案:使用多行插入:最简单的方法是使用多行插入语句,将多条记录一次性插入到数据库。这比逐条插入要快得多,因为减少了连接和查询的开销。$values = [];for ($i = 0; $i < 1000000......
  • 路径规划算法:基于跳蛛优化的机器人路径规划算法- 附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 路径规划算法:基于材料生成优化的机器人路径规划算法- 附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • Flink Unaligned Checkpoint 在 Shopee 的优化和实践
    一、Checkpoint存在的问题1.1数据库的Snapshot和恢复机制首先看一下数据库的Snapshot和恢复机制。数据库周期性地快照,每一次Snapshot是一个全量快照,同时要持续地写ChangeLog或WAL。当数据库crash后,新的数据库实例会从Snapshot3以及最新的ChangeLog恢复。1.2Fli......
  • php实战手册(2)
    目录变量变量定义<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>phpdemo</title></head><body> <?php$x=11;?> <p> phphello,world ......
  • Python 递归
    ##py_recursive.py#py_learn##CreatedbyZ.Steveon2023/8/721:28.##需求:通过递归查找一个目录下的所有目录和文件os模块下的三个方法:1.os.listdir()2.os.path.isdir()os.path.isdir(path)如果path是现有的目录,则返回#True。本方法会跟踪符号......