php递归生成树
最近开发过程中遇到一个小问题,要求将一些数据转换为树形结构,类似于
[ 'name' => 'root', 'children' => [ [ 'name' => 'first', 'children' => [ [ 'name' => 'first-first', 'children' => [] ], [ 'name' => 'first-two', 'children' => [] ],], ], [ 'name' => 'two', 'children' => [ [ 'name' => 'two-first', 'children' => [] ], [ 'name' => 'two-two', 'children' => [] ],], ] ]];
提供的数据结构是这种类型
看上去是个树形结构,再结合前面的数据格式,所以脑海中很简单的就冒出了方法——用递归。
虽然之前写过一些递归,但真正用于这种项目还是头一次,当中也是遇到不少错误,所以算法以及数据结构扎实还是很有必要的。
关于递归之类的定义就不多说了,简单来说就是分而治之,大事化小,小事化了这种,所以,我们从最简单的开始考虑,这里采用的是自底向上的方式建立树
1.如何处理 最后一列的数据,即将其变为一个数组
看上面这个数据结构,似乎有点头疼?没关系,只要忽略掉其他不必要的东西就行
现在,数据结构在我们眼中是这个样子
现在,问题是不是一下子简单起来?
那么,这是我的代码
$data = ' 电话沟通 电子邮件沟通 短信沟通 移动平台沟通 其他沟通方式'; $data = explode("\r\n", $data); $newData = []; foreach ($data as $v) { $newData[] = [ 'name' => $v, 'children' => [] ]; } print_r($newData);
特别注意其中的”\r\n”,不要使用单引号,单引号当中的数据是不会被转义的
php的数组十分强大,所以这里我将其分割为数组,方便处理,接着就是日常操作了,跑个循环就出来了
2.第二步,如何处理有级联的
现在,我们眼中的数据结构是这样的
如何处理?继续用for循环?似乎有点难处理,那么,这个时候就是递归的出现了
或许你会有其他、更好的想法, 但是我的代码是这样的
/** * @param $data * @param $index * @return array */ function recursive(&$data, $index) { $temp = []; while (true) { $str = next($data); if (!$str) return $temp; $currentIndex = 0; $str = str_replace("\t", '', $str, $currentIndex); if ($currentIndex <= $index) { prev($data); return $temp; } $temp[] = [ 'children' => recursive($data, $currentIndex), 'name' => $str, ]; } } $data = ' 沟通方式 电话沟通 电子邮件沟通 短信沟通 移动平台沟通 其他沟通方式 销售方式'; $data = explode("\r\n", $data); print_r(recursive($data, -1));
突然有些头大?那就对了——容我慢慢道来
首先如何解决读取数据的问题?
在这里我通过php数组自带的next和prev控制着数组,来获取每条数据
接着,替换掉前面tab符号,currentIndex用于记录是第几级,整个函数最重要的部分是这段
if ($currentIndex <= $index) { prev($data); return $temp; }
这段用于第三级别与第二级之间的过渡,如果不使用prev($data);
那么 “其他沟通方式”的children 中就会包含 “销售方式”
造成层级不对,之后就是递归的常规操作,调用自己
其中你可能注意到,最开始调用的时候传递的index 是 -1
print_r(recursive($data, -1));
这样可以可以防止第一个 沟通方式 被跳过
如此,可能会比较绕,但逻辑上还是挺清晰的,建议有迷惑的同学可以自己断点,一步步查看
sb ba ni
????