资讯专栏INFORMATION COLUMN

分层数据Hierarchical Data探索(1.递归)

yzd / 2066人阅读

摘要:分层数据探索例如无限级分类多级菜单省份城市引言什么是分层数据类似于树形结构,除了根节点和叶子节点外,所有节点都有一个父节点和一个或多个子节点。接下来我会先通过一般方法和递归方法来实现无限极分类,然后再通过两种数据模型来谈一谈分层数据的处理。

分层数据Hierarchical Data探索(例如:无限级分类、多级菜单、省份城市) 引言

什么是分层数据?

类似于树形结构,除了根节点和叶子节点外,所有节点都有一个父节点和一个或多个子节点。

大多数同学都曾在数据库中处理过分层数据(hierarchical data),分层数据存在于许多基于数据库的应用程序中,包括论坛和邮件列表中的分类、商业组织图表、内容管理系统的分类、产品分类、无限级分类、多级菜单、省份城市等等。但是因为关系数据库中的表没有层次关系,只是简单的平面化的列表;而分层数据具有父-子关系,显然关系数据库中的表不能自然地表现出其分层的特性。

接下来我会先通过一般方法和递归(recursion)方法来实现无限极分类,然后再通过两种数据模型来谈一谈分层数据的处理。

分层数据Hierarchical Data探索(1.递归 recursion)

分层数据Hierarchical Data探索(2.邻接表模型 Adjacency List Model)

分层数据Hierarchical Data探索(3.嵌套集合模型 Nested Set Model)

三种方式的变量传递

& 引用赋值

function doloop1(&$i = 1)
{
    print_r($i);
    $i++;
    if ($i <= 10) {
        doloop1($i);
    }
}
doloop1();

static 静态变量

function doloop2()
{
    static $i = 1;
    print_r($i);
    $i++;
    if ($i <= 10) {
        doloop2();
    }
}

doloop2();

global 全局变量

$i = 1;
function doloop3()
{
    global $i;
    echo $i;
    $i++;
    if ($i <= 10) {
        doloop3();
    }
}
doloop3();
构建模拟数据
# 模拟数据
       $data = [
            ["id" => 1, "title" => "Electronics", "parent_id" => 0],
            ["id" => 2, "title" => "Laptops & PC", "parent_id" => 1],
            ["id" => 3, "title" => "Laptops", "parent_id" => 2],
            ["id" => 4, "title" => "PC", "parent_id" => 2],
            ["id" => 5, "title" => "Cameras & photo", "parent_id" => 1],
            ["id" => 6, "title" => "Camera", "parent_id" => 5],
            ["id" => 7, "title" => "Phones & Accessories", "parent_id" => 1],
            ["id" => 8, "title" => "Smartphones", "parent_id" => 7],
            ["id" => 9, "title" => "Android", "parent_id" => 8],
            ["id" => 10, "title" => "iOS", "parent_id" => 8],
            ["id" => 11, "title" => "Other Smartphones", "parent_id" => 8],
            ["id" => 12, "title" => "Batteries", "parent_id" => 7],
            ["id" => 13, "title" => "Headsets", "parent_id" => 7],
            ["id" => 14, "title" => "Screen Protectors", "parent_id" => 7],
        ];
获取无限极分类
/**
 * 值引用获取无限极分类树
 * 
 * @param array $data
 * @return array
 */
function make_tree($data)
{  
    $refer = array();  
    $tree = array();  
    foreach($data as $k => $v){  
        $refer[$v["id"]] = & $data[$k];  //创建主键的数组引用  
    }  

    foreach($data as $k => $v){  
        $parent_id = $v["parent_id"];   //获取当前分类的父级id  
        if($parent_id == 0){  
            $tree[] = & $data[$k];   //顶级栏目
        }else{  
            if(isset($refer[$parent_id])){  
                $refer[$parent_id]["children"][] = & $data[$k];  //如果存在父级栏目,则添加进父级栏目的子栏目数组中  
            }  
        }  
    }  

    return $tree;  
}

/**
 * 递归获取无限极分类树
 * 
 * @param array $data
 * @param int $parent_id
 * @param int $level
 * @return array
 */
function make_tree2($data = [], $parent_id = 0, $level = 0)
{
    $tree = [];
    if ($data && is_array($data)) {
        foreach ($data as $v) {
            if ($v["parent_id"] == $parent_id) {
                $tree[] = [
                    "id" => $v["id"],
                    "level" => $level,
                    "title" => $v["title"],
                    "parent_id" => $v["parent_id"],
                    "children" => make_tree2($data, $v["id"], $level + 1),
                ];
            }
        }
    }
    return $tree;
}
获取子节点以及节点的层级
/**
 * 引用赋值方式
 * @param array $data
 * @param int $id
 * @param int $level
 * @return array
 */
function getSubTree($data = [], $id = 0, $level = 0)
{
    static $tree = [];

    foreach ($data as $key => $value) {
        if ($value["parent_id"] == $id) {
            $value["laravel"] = $level;
            $tree[] = $value;
            getSubTree($data, $value["id"], $level + 1);
        }
    }
    return $tree;
}

/**
 * 静态变量方式
 * @param array $data
 * @param int $id
 * @param int $level
 * @return array
 */
function getSubTree($data = [], $id = 0, $level = 0)
{
    static $tree = [];

    foreach ($data as $key => $value) {
        if ($value["parent_id"] == $id) {
            $value["laravel"] = $level;
            $tree[] = $value;
            getSubTree($data, $value["id"], $level + 1);
        }
    }
    return $tree;
}


/**
 * 全局变量方式
 * @param array $data
 * @param int $id
 * @param int $level
 * @return array
 */

$tree = [];  //先申明变量
function getSubTree($data = [], $id = 0, $level = 0)
{
    global $tree;

    foreach ($data as $key => $value) {
        if ($value["parent_id"] == $id) {
            $value["laravel"] = $level;
            $tree[] = $value;
            getSubTree($data, $value["id"], $level + 1);
        }
    }
    return $tree;
}
通过pid获取所有上级分类 常用于面包屑导航
/**
 * getParentsByParentId2($categories, 9)
 *
 * @param array $data
 * @param $parent_id
 * @return array
 */
function getParentsByParentId($data = [], $parent_id)
{
    static $categories = [];

    if ($data && is_array($data)) {
        foreach ($data as $item) {
            if ($item["id"] == $parent_id) {
                $categories[] = $item;
                getParentsByParentId($data, $item["parent_id"]);
            }
        }
    }
    return $categories;
}

function getParentsByParentId2($data = [], $parent_id)
{
    $categories = [];

    if ($data && is_array($data)) {
        foreach ($data as $item) {
            if ($item["id"] == $parent_id) {
                $categories[] = $item;
                $categories = array_merge($categories, getParentsByParentId2($data, $item["parent_id"]));
            }
        }
    }
    return $categories;
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31492.html

相关文章

  • 分层数据Hierarchical Data探索(2.邻接表模型)

    摘要:分层数据探索例如无限级分类多级菜单省份城市引言第一篇分层数据探索递归已经介绍了分层数据以及使用递归算法实现了无限极分类,但是递归即浪费时间,又浪费空间内存尤其是在数据量大的情况下效率显著下降。 分层数据Hierarchical Data探索(例如:无限级分类、多级菜单、省份城市) 引言 第一篇 分层数据Hierarchical Data探索(1.递归)已经介绍了分层数据以及使用递归算法...

    Scott 评论0 收藏0
  • 递归的艺术 - 深度递归网络在序列式推荐的应用

    摘要:因为在每一时刻对过去的记忆信息和当前的输入处理策略都是一致的,这在其他领域如自然语言处理,语音识别等问题不大,但并不适用于个性化推荐,一个用户的听歌点击序列,有正负向之分。 在内容爆炸性增长的今天,个性化推荐发挥着越来越重要的作用,如何在海量的数据中帮助用户找到感兴趣的物品,成为大数据领域极具挑战性的一项工作;另一方面,深度学习已经被证明在图像处理,计算机视觉,自然语言处理等领域都取得了不俗...

    ZweiZhao 评论0 收藏0
  • DeepMind 提出分层强化学习新模型 FuN,超越 LSTM

    摘要:实验蒙特祖玛的复仇蒙特祖玛的复仇是上最难的游戏之一。图蒙特祖玛的复仇的学习曲线在第一个房间中学习的子目标的可视化呈现。结论如何创建一个能够学习将其行为分解为有意义的基元,然后重新利用它们以更有效地获取新的行为,这是一个长期存在的研究问题。 论文题目:分层强化学习的 FeUdal 网络(FeUdal Networks for Hierarchical Reinforcement Learnin...

    dailybird 评论0 收藏0
  • 理解开发HD钱包涉及的BIP32、BIP44、BIP39

    摘要:本文首发于深入浅出区块链社区原文链接理解开发钱包涉及的原文已更新,请读者前往原文阅读如果你还在被钱包搞的一头雾水,来看看这边文章吧。所以我们要开发以太坊钱包同样需要对比特币的钱包提案有所了解。 本文首发于深入浅出区块链社区原文链接:理解开发HD钱包涉及的BIP32、BIP44、BIP39原文已更新,请读者前往原文阅读 如果你还在被HD钱包、BIP32、BIP44、BIP39搞的一头雾水...

    firim 评论0 收藏0
  • 理解开发HD钱包涉及的BIP32、BIP44、BIP39

    摘要:本文首发于深入浅出区块链社区原文链接理解开发钱包涉及的原文已更新,请读者前往原文阅读如果你还在被钱包搞的一头雾水,来看看这边文章吧。所以我们要开发以太坊钱包同样需要对比特币的钱包提案有所了解。 本文首发于深入浅出区块链社区原文链接:理解开发HD钱包涉及的BIP32、BIP44、BIP39原文已更新,请读者前往原文阅读 如果你还在被HD钱包、BIP32、BIP44、BIP39搞的一头雾水...

    tianren124 评论0 收藏0

发表评论

0条评论

yzd

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<