我们知道数据库一般是以一个列表(id,pid)的形式保存树的。如何提取这棵树呢?最简单的方法就是根据pid循环查表。但是毫无疑问,这会产生巨大的数据库查询开销。

那么一般建议的方法是一次性将全部相关数据全查出来,但是这就涉及到一个问题,如何快速的构建一棵树。

我曾经一直以为,这是一个复杂的操作,至少需要一个递归,时间复杂度不会是O(n)。

前段时间,一个工作上的需求,需要解决这个问题。我仔细想了想,发现完全可以通过单层循环解决这个问题,实现如下:

 function list2Tree($listItem, $idx = 'id', $pIdx = 'pid', $childKey= 'list'){
$map = array();
$pMap = array(); foreach($listItem as $item){
$id = $item[$idx];
$pid = $item[$pIdx];
$map[$id] = &$item;
unset($item);
} foreach($map as $id => &$item){
$pid = $item[$pIdx];
empty($item[$childKey]) && $item[$childKey] = array(); if(! isset($map[$pid])){
$pMap[$id] = &$item;
}
else{
$pItem= &$map[$pid];
$pItem[$childKey][] = &$item;
} unset($item, $pItem);
} return array_shift($pMap);
}

测试一下:

 // 路径方便识别父子关系
$json = <<<JSON
[
{
"id": 2,
"pid": 1,
"path": "/se"
},
{
"id": 3,
"pid": 2,
"path": "/se/4901"
},
{
"id": 4,
"pid": 5,
"path": "/se/4901/mask/query"
},
{
"id": 5,
"pid": 3,
"path": "/se/4901/mask"
},
{
"id": 6,
"pid": 2,
"path": "/se/4902"
},
{
"id": 7,
"pid": 6,
"path": "/se/4902/mask"
}
]
JSON; $list = json_decode($json, true); var_dump(list2Tree($list));

结果:

array(4) {
["id"]=>
int(2)
["pid"]=>
int(1)
["path"]=>
string(3) "/se"
["list"]=>
array(2) {
[0]=>
array(4) {
["id"]=>
int(3)
["pid"]=>
int(2)
["path"]=>
string(8) "/se/4901"
["list"]=>
array(1) {
[0]=>
array(4) {
["id"]=>
int(5)
["pid"]=>
int(3)
["path"]=>
string(13) "/se/4901/mask"
["list"]=>
array(0) {
}
}
}
}
[1]=>
array(4) {
["id"]=>
int(6)
["pid"]=>
int(2)
["path"]=>
string(8) "/se/4902"
["list"]=>
array(1) {
[0]=>
array(4) {
["id"]=>
int(7)
["pid"]=>
int(6)
["path"]=>
string(13) "/se/4902/mask"
["list"]=>
array(0) {
}
}
}
}
}
}

成功把列表转成了树

将含有父ID的列表转成树的更多相关文章

  1. 传递一个父id返回所有子id的用法,可用于删除父级以下的所有子级

    先在common文件夹建立一个function.php文件,然后写一个递归函数,传递一个父id返回所有子id,如下: function getChildrenId($node,$pid){ $arr= ...

  2. vue通过id从列表页跳转到对应的详情页

    1. 列表页:列表页带id跳转到详情页 详情页:把id传回到后台就可以获取到数据了 2.列表页跳转到详情页并更改详情页的标题 列表页:带id和页面标题的typeid跳转到详情页 详情页:在html绑定 ...

  3. VUE通过id从列表页跳转到相对的详情页

    新闻列表页面: 在这里我用a标签进行跳转,在vue里面可以这样写<router-link></router-link> 1 <router-link :to=" ...

  4. 无限极分类,传递一个父ID,返回所有子集

    方法: static public function getChildren($data,$pid){ $arr=array(); foreach ($data as $v) { if ($v['pi ...

  5. Oracle由ID生成父ID的函数

    /*表结构*/ CREATE TABLE ly_md ( bh BYTE), mc BYTE), pym BYTE), f_bh BYTE), ch NUMBER, ID NUMBER ); INSE ...

  6. MySQL中进行树状所有子节点的查询 . mysql根据父id 查询所有的子id

    在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. ...

  7. 递归根据父ID 找所有子类ID

    function getinfo($pid){ $str = ''; $row = M('user')->where(array('pid'=>$pid))->select(); i ...

  8. ajax通过新闻id获取列表

    <div class="index_main">        <div class="page_l">           <i ...

  9. SQL在一张表中根据父ID获取所有的子ID

    with a as ( select id,name,parentid from categories where id=53 union all select x.id,x.name,x.paren ...

随机推荐

  1. html5与EmguCV前后端实现——人脸识别篇(一)

    上个月因为出差的关系,断更了很久,为了补偿大家长久的等待,送上一个新的系列,之前几个系列也会抽空继续更新. 大概半年多前吧,因为工作需要,我开始研究图像识别技术.OpenCV在这方面已经有了很多技术积 ...

  2. VS2013中使用GDI+绘图

    VC范例,400多个例子源代码下载 http://download.csdn.net/detail/bigtree_mfc/7727977 VS2013中使用GDI+绘图和VC6.0不同,在VC6.0 ...

  3. BZOJ3401: [Usaco2009 Mar]Look Up 仰望

    3401: [Usaco2009 Mar]Look Up 仰望 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 87  Solved: 58[Submit ...

  4. js跨越小结

    javascript跨域有几种情况: 1.基于同一父域的子域之间,如:a.c.com和b.c.com 2.基于不同的父域之间,如:www.a.com和www.b.com 3.端口的不同,如:www.a ...

  5. 基于HTML5 Canvas的饼状图表实现教程

    昨天我们分享了一款基于HTML5的线性图表应用,效果非常不错,可以看在线DEMO或者实现教程.今天我们继续来分享一款基于HTML5的网页图表,它也是利用Canvas绘制的,但是和前面不同的是,这款图表 ...

  6. SPOJ694 -- DISUBSTR 后缀树组求不相同的子串的个数

    DISUBSTR - Distinct Substrings   Given a string, we need to find the total number of its distinct su ...

  7. oracle exp imp

    oracle exp/imp

  8. 形形色色的软件生命周期模型(4)——MSF、实用型

    摘要: 读大学时,我们曾经学习过不少软件生命周期模型,当时还不是很懂软件开发,你可能会觉得这些东西很新奇.在实际工作中,你会发现这些模型其实很难应用,与此同时你会接触到RUP.MSF等权威软件公司的生 ...

  9. POJ 3723 Conscription

    Conscription Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6325   Accepted: 2184 Desc ...

  10. MySQL事务处理2

    MySQL5.X 都已经发布好久了,但是还有很多人认为MySQL是不支持事务处理的,这不得不怪他们是孤陋寡闻的,其实,只要你的MySQL版本支持BDB或 InnoDB表类型,那么你的MySQL就具有事 ...