我们知道数据库一般是以一个列表(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. MYSQL如何导出存储过程和触发器?

    今天遇到.. 类似下面的就可以: mysqldump -u root -p -ntd -R  nxsc>nxsc_trigger.sql

  2. Qt编程之Qt样例表(QSS)

    For a long time, Qt has allowed you to decorate your GUIs with CSS’ish style sheets. Inspired by the ...

  3. Android开发 解决AlertDialog中的EditText无法调出输入法的问题

    在AlertDialog中使用自定义的View,如果View中有EditText,在上面点击,默认是跳不出软键盘的,不是焦点的问题.解决方法,有两种,一是把AlertDialog换成Dialog,但这 ...

  4. AcitonBar 自定义布局

    Android系统中ActionBar默认的布局不美观且难于控制,通过为ActionBar自定义布局的方式可以灵活控制ActionBar. 自定义Activity主题和ActionBar样式 在新建的 ...

  5. 【HDOJ】1057 A New Growth Industry

    纯粹的模拟题目. #include <cstdio> #include <cstring> #include <cstdlib> #define MAXN 20 # ...

  6. 【转】我的Android笔记(十)—— ProgressDialog的简单应用,等待提示

    原文网址:http://blog.csdn.net/barryhappy/article/details/7376231 在应用中经常会用到一些费时的操作,需要用户进行等待,比如加载网页内容…… 这时 ...

  7. POJ_2488——骑士遍历棋盘,字典序走法

    Description Background The knight is getting bored of seeing the same black and white squares again ...

  8. eclipse 解决插件失效

    昨天系统崩溃,重装系统后eclipse突然对links方式加载插件失效.用尽了网上各种解决方法,始终不行.在%eclispe_dir%/configration/org.eclipse.update/ ...

  9. css的存在形式以及优先级

    css的存在形式以及优先级 css不仅仅可以在每个head标签中定义,而且也可以写在一个文件中,每个页面即可进行引用,这样可以做到重复利用. css文件的写法如下: common.css .c1{ h ...

  10. Highcharts 时间序列,可缩放的图表

    配置 图表 配置可缩放图表. chart.zoomType 指定了用户可以拖放的尺寸,用户可以通过拖动鼠标来放大,可能值是x,y或xy: var chart = { zoomType: 'x' }; ...