https://blog.csdn.net/rghanbing4/article/details/51284131
<pre name="code" class="php"><pre name="code" class="php"><?php $arr = array( array('id' => 111, 'pid' => 0, 'name' => '江西省'), array('id' => 5, 'pid' => 2, 'name' => '鸡西市'), array('id' => 2, 'pid' => 0, 'name' => '黑龙江省'), array('id' => 3, 'pid' => 111, 'name' => '南昌市'), array('id' => 6, 'pid' => 4, 'name' => '香坊区'), array('id' => 27, 'pid' => 4, 'name' => '南岗区'), array('id' => 8, 'pid' => 6, 'name' => '和兴路'), array('id' => 9, 'pid' => 27, 'name' => '西大直街'), array('id' => 10, 'pid' => 8, 'name' => '东北林业大学'), array('id' => 11, 'pid' => 9, 'name' => '哈尔滨工业大学'), array('id' => 12, 'pid' => 8, 'name' => '哈尔滨师范大学'), array('id' => 13, 'pid' => 111, 'name' => '赣州市'), array('id' => 14, 'pid' => 13, 'name' => '赣县'), array('id' => 15, 'pid' => 13, 'name' => '于都县'), array('id' => 16, 'pid' => 14, 'name' => '茅店镇'), array('id' => 17, 'pid' => 14, 'name' => '大田乡'), array('id' => 18, 'pid' => 16, 'name' => '义源村'), array('id' => 19, 'pid' => 16, 'name' => '上坝村') ); static $_arr2 = array(); //用于存放整理好的数据 /** * 对数组按照子父类顺序整理,并且直接获取栏目的所有子栏目数 * @param array $_arr2 用于存放整理结果的数组 * @param array $arr 需要整理的数组 * @param number $pid 父栏目id,会递归找出该父亲栏目下的所有子栏目 * @param number $level 第几级 * @return array $num 子栏目数 */ function getTreeAndNum(&$_arr2, $arr, $pid=0, $level=0 ,$isClear=FALSE){ if($isClear) $_arr2 = array(); $num = 0; foreach($arr as $k => $v){ if($v['pid'] == $pid){ $v['level'] = $level; $_arr2[$v['id']] = $v; $num ++; $allnum = getTreeAndNum($_arr2, $arr, $v['id'], $level+1); $_arr2[$v['id']]['num'] = $allnum; $num = $num + $allnum; } } return $num; } /** * 对数组按照子父类顺序整理 * @param array $arr 需要整理的数组 * @param number $pid 父栏目id * @param number $level 第几级 * @return array $_arr 整理好的数组 */ function getTree($arr, $pid=0, $level=0, $isClear=FALSE){ //因为不断调用自己的时候,会不断开辟新的空间,空间与空间之间的变量是不能共享的,可//以存放到静态数组中,实现共享 static $_arr = array(); if($isClear) $_arr = array(); foreach($arr as $k => $v){ if($v['pid'] == $pid){ $v['level'] = $level; $_arr[] = $v; getTree($arr, $v['id'], $level+1); } } return $_arr; } /** * 获取一个栏目的所有子栏目数 * @param array $arr 数组 * @param number $catId 父栏目 * @return number $_ret 一个栏目的子栏目数 */ function getChildrenNums($arr, $catId, $isClear=FALSE) { static $_ret = 0; if($isClear) $_ret = 0; foreach ($arr as $k => $v) { if($v['pid'] == $catId) { $_ret++; getChildrenNums($arr, $v['id']); } } return $_ret; } /** * 获取列表树,此方法先遍历整理好的数组,在遍历的过程中再次去调用函数获取该栏目的所有子栏目数目 * @param unknown $arr 数组 */ function getList($arr){ foreach($arr as $k => $v){ echo str_repeat('-', 4*$v['level']).$v['name'].'('.getChildrenNums($arr, $v['id'], TRUE).')'.'<br/>'; } } function getNewList($arr){ foreach($arr as $k => $v){ echo str_repeat('-', 4*$v['level']).$v['name'].'('.$v['num'].')'.'<br/>'; } } /** * 返回当前的时间,以秒为单位 * @return number */ function getMicTime(){ return time(); } /** * 性能测试,由于数据量比较小,循环后才能见到差距,数据量大的话,差距会明显些 * 总结来说,方案2的效率会高些 */ echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'; /****************方案1**********************/ $time1 = getMicTime(); for($i = 0; $i < 4000; $i++){ $arr = getTree($arr, $pid=0, $level=0, TRUE); getList($arr); } $time2 = getMicTime(); echo '方案1的性能为:'.($time2-$time1).'<br>'; /****************方案2**********************/ $time3 = getMicTime(); for($i = 0; $i < 4000; $i++){ getTreeAndNum($_arr2, $arr, $pid=0, $level=0 ,TRUE); getNewList($_arr2); } $time4 = getMicTime(); echo '方案2的性能为:'.($time4-$time3).'<br>';
如果要对列表的某个数据字段累加和:
static $result = []; self::_getTotalCount($result, $list, 0, 0 ,TRUE); private static function _getTotalCount(&$result, $arr, $pid=0, $level=0 ,$isClear=FALSE){ if($isClear){ $result = []; } $num = 0; foreach($arr as $k => $v){ if($v['pid'] == $pid){ $v['level'] = $level; $result[$v['id']] = $v; $num += $v['count']; $all_num = self::_getTotalCount($result, $arr, $v['id'], $level+1); $result[$v['id']]['total'] = $all_num + $v['count']; $num = $num + $all_num; } } return $num; }