递归教程:一份可疑的暧昧名单

422次阅读
一条评论

最近处理了一次无限分类的数据,主要是用到了递归函数,当然 laravel 有更优雅的关联查询办法,不过由于数据需要有很多其他二次修改,于是采用了原生的递归处理,同时对于递归的原理,采用一个形象的比喻来说明:

(核心思路:递归有去有回)

官方说明

递归函数即自调用函数,也就是函数在函数体内部直接或间接地自己调用自己。需要注意的是使用递归函数时通常会在函数体中附加一个判断条件,以判断是否需要继续执行递归调用,当条件满足时会终止函数的递归调用。

背景说明

突然的一天,现任女友发现你还和以前的一些女性朋友保持联系,并且找到了一份证据摆到你的面前,让你解释一下你跟他们之间的关系,相关证据如下:

<?php
// 出处:https://www.dongyao.ren/
$arr = [
    [
        'id' =>1,
        'pid'=>0,
        'name' => '前女友'
    ],
    [
        'id' =>2,
        'pid'=>1,
        'name' =>'二毛'
    ],
    [
        'id' =>3,
        'pid'=>0,
        'name' =>'可疑人员'
    ],
    [
        'id' =>4,
        'pid'=>2,
        'name' =>'小红'
    ],
    [
        'id' =>5,
        'pid'=>2,
        'name' =>'小绿'
    ],
    [
        'id' =>6,
        'pid'=>3,
        'name' =>'同事'
    ],
    [
        'id' =>7,
        'pid'=>1,
        'name' =>'大毛'
    ],
    [
        'id' =>8,
        'pid'=>3,
        'name' =>'同学'
    ]
];

相关证人

现任女友严厉发话了,你自己交代后果可能会好一点,要不然她就要去问下面这个证人朋友了:

<?php
// 出处:https://www.dongyao.ren/
getMenu($menus_main,$parent_id=0,$sub='children',$level=1){$data = array();
        foreach($menus_main as $key=>$val){if($val['parent_id']==$parent_id){$val['level']=$level;
                $val[$sub]=$this->getMenu($menus_main,$val['id'],$sub,$level+1);
                $data[] = $val;
            }
        }
        return $data;
    }

主动交代

以下是这些名单的关系图谱,目前已经一头冷汗了

递归教程:一份可疑的暧昧名单

回忆一下细节吧#

现任要求你讲述一下跟这些人的认识细节,已经证据确凿了,就别硬撑了
把刚才那个证人来过来一起回忆一下,经过讨论,确定了一个思路,如下:

<?php
// 出处:https://www.dongyao.ren/
function getMenu($menus_main,$pid=0,$sub='children',$level=1,$name = '主栏目'){$data = array();
    foreach($menus_main as $key=>$val){echo "正在第".$level."层排查第".$val['id']."号人物 (Pid:".$val['pid']."):<span style='color:red'><b>".$val['name']."</b></span> 属于【".$name."】--- 此时 data 值".json_encode($data,JSON_UNESCAPED_UNICODE);

        if($val['pid']==$pid){echo "<span style='color:green'>:证据确凿,继续排查".($level+1)."层 </span><hr>";
            $val['level']=$level;
            // unset($menus_main[$key]);
            $val[$sub]=getMenu($menus_main,$val['id'],$sub,$level+1,$val['name']);
            $data[] = $val;
        }else{if($val['id'] == $pid){echo "<span style='color:red'>--- 条件不满足【自己查自己】,开始返回 ---</span><hr>";
            }else{echo "<span style='color:red'>--- 条件不满足【不是同一类】,开始返回 ---</span><hr>";
            }

        }

    }
    return $data;
}

得到了具体的聊天过程如下:

递归教程:一份可疑的暧昧名单

…… 还有好多没列出来

内容过多,一口气说不完,说重点

相关过程

对照关系图谱和这一份聊天记录可以看到:

由于过程比较紧张,手抖画的图,大概意思就是这么一个简化图

递归教程:一份可疑的暧昧名单
  • 首先对号人物前女友进行排查,确定这是个大号人物。此时由于不确定这个大人物下面还有没有其他相关人物,所以,先放在待定区 此时 $data 变量还未赋值
  • 第二轮就是排查所有人是不是都跟 前女友 有关系,一个一个审问之后,暂时排除无关人员;
  • 刚开始就遇上自己查自己的情况,跳过,该人物第一步已经确定了
  • 第二位 二毛 进入视线了,确定跟 前女友 有关,满足调查条件,此时 二毛后面的人员,先原地等待不要动,等查完二毛再处理
  • 此时进入调查 二毛 的关系链工作中,继续把 8 位关键人物拉过来,询问是否跟二毛有关系
  • 问到 小红 这里,发现小红是 二毛 的孩子,满足调查条件  , 继续把 8 位关键人物拉过来,询问是否跟 小红 有关系
  • 发现没有人跟小红有关系了,此时就把 小红 二毛 孩子的信息标记到 $data 变量当中

到这一步,其中一条关系链已经调查清除,赋值 $data,当前只有小红一人被标记赋值,当前其他关系链的相关人物还在等待调查,继续往下看:

  • 回过头去,继续到上次中断调查的位置,从 小红 往后继续调查,然后发现了 小绿 也是 二毛 的孩子,后续工作跟 小红 一样。
  • 得出 小绿 没有关联人物了,退出当前关系链,将调查结果追加到上一步的后面

此时,$data 变量当中包含两个人物了,有小红,还有小绿,后续工作继续

  • 回到上次中断的位置,$data 当前包含二毛和两个孩子的总信息,然后继续从 二毛 后面调查,发现 大毛 也是 前女友 阵营的,后续关系链调查跟二毛一样:

一圈调查下来,发现大毛还算简单,没有孩子,结束对他的调查,把大毛的调查结果,记录在 $data 当中,此时 data 变量包含了大毛和二毛,以及他们的孩子关系信息。

……
后续其他关系链的逻辑同上,反反复复,一个一个的审问调查,发现可疑就暂时中断,后续的,顺着可疑人员排查下去,排查完之后,登记排查结果,回过头再来从中断位置继续深挖下去,如此反复。

证据链

下方是本次过程的所有代码,各位可以自行执行参阅

<?php
// 出处:https://www.dongyao.ren/
function getMenu($menus_main,$pid=0,$sub='children',$level=1,$name = '主栏目'){$data = array();
    foreach($menus_main as $key=>$val){echo "正在第".$level."层排查第".$val['id']."号人物 (Pid:".$val['pid']."):<span style='color:red'><b>".$val['name']."</b></span> 属于【".$name."】--- 此时 data 值".json_encode($data,JSON_UNESCAPED_UNICODE);

        if($val['pid']==$pid){echo "<span style='color:green'>:证据确凿,继续排查".($level+1)."层 </span><hr>";
            $val['level']=$level;
            // unset($menus_main[$key]);
            $val[$sub]=getMenu($menus_main,$val['id'],$sub,$level+1,$val['name']);
            $data[] = $val;
        }else{if($val['id'] == $pid){echo "<span style='color:red'>--- 条件不满足【自己查自己】,开始返回 ---</span><hr>";
            }else{echo "<span style='color:red'>--- 条件不满足【不是同一类】,开始返回 ---</span><hr>";
            }

        }

    }
    return $data;
}


$arr = [
    [
        'id' =>1,
        'pid'=>0,
        'name' => '前女友'
    ],
    [
        'id' =>2,
        'pid'=>1,
        'name' =>'二毛'
    ],
    [
        'id' =>3,
        'pid'=>0,
        'name' =>'可疑人员'
    ],
    [
        'id' =>4,
        'pid'=>2,
        'name' =>'小红'
    ],
    [
        'id' =>5,
        'pid'=>2,
        'name' =>'小绿'
    ],
    [
        'id' =>6,
        'pid'=>3,
        'name' =>'同事'
    ],
    [
        'id' =>7,
        'pid'=>1,
        'name' =>'大毛'
    ],
    [
        'id' =>8,
        'pid'=>3,
        'name' =>'同学'
    ]
];
getMenu($arr);return;

加入官方交流QQ群:778957856
post-qrcode
clark
版权声明:本站原创文章,由 clark 2021-12-22发表,共计3635字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(一条评论)
验证码
jock 评论达人 LV.1
2021-12-27 10:34:38 回复

学习了~

MacintoshMacintoshEdgeEdge96.0.1054.62