如何返回通过递归查找得到的数组元素?Menu类场景求助
嘿,我来帮你搞定这个递归查找的问题!我看你已经定义了带有多层嵌套$_data数组的Menu类,现在需要写一个递归函数定位指定元素并返回它。这里的核心坑点是正确处理递归的返回值——很多人写递归时会忽略这一点,导致找到结果却无法传递到上层调用。
完整代码实现
我直接给你写好带递归查找方法的Menu类,这里假设你是按id查找元素(如果需要按其他字段匹配,后面我会告诉你怎么扩展):
class Menu { private $_data = []; public function __construct() { $this->_data = array( "Parent1" => array( "Child1" => array( "id" => 1, "minQuantity" => 2, "maxQuantity" => 10, "cost" => 5.99, ), "Child2" => array( "id" => 2, "minQuantity" => 1, "maxQuantity" => 5, "cost" => 3.99, ) ), "Parent2" => array( "Child3" => array( "id" => 3, "minQuantity" => 3, "maxQuantity" => 15, "cost" => 7.99, ) ) ); } /** * 递归查找指定ID的菜单项 * @param int $targetId 要查找的目标ID * @param array|null $currentData 当前遍历的数组,默认使用类的私有$_data * @return array|null 找到的菜单项数组,未找到则返回null */ public function findMenuItemById(int $targetId, ?array $currentData = null): ?array { // 初始化当前遍历的数组,第一次调用时用类的$_data if ($currentData === null) { $currentData = $this->_data; } foreach ($currentData as $item) { // 判断当前元素是否是具体的菜单项(包含id字段) if (isset($item['id'])) { if ($item['id'] === $targetId) { // 找到匹配项,直接返回 return $item; } } else { // 如果是子菜单集合,递归深入查找 $foundItem = $this->findMenuItemById($targetId, $item); // 递归返回结果不为空,说明找到了,立刻向上传递结果 if ($foundItem !== null) { return $foundItem; } } } // 遍历完所有元素都没找到,返回null return null; } } // 使用示例 $menu = new Menu(); $targetItem = $menu->findMenuItemById(2); print_r($targetItem); // 输出结果: // Array ( // [id] => 2 // [minQuantity] => 1 // [maxQuantity] => 5 // [cost] => 3.99 // )
关键要点说明
递归的终止条件:
- 找到匹配的元素时,直接返回该元素数组
- 遍历完当前层级所有元素仍未找到,返回
null
不要忽略递归的返回值:
当你递归调用findMenuItemById时,必须检查返回结果。如果递归找到了元素,要立刻把这个结果返回给上层调用,而不是继续遍历其他元素——这是很多人写递归时容易犯的错误,会导致找到的结果被“丢掉”。层级区分:
我们通过isset($item['id'])来区分“父菜单集合”和“具体菜单项”,你可以根据自己的数组结构调整这个判断逻辑(比如如果你的父菜单也有特定标识字段)。
扩展:更灵活的匹配方式
如果你需要按其他条件查找(比如cost范围、minQuantity等),可以把匹配逻辑做成回调函数,让方法更通用:
public function findMenuItem(callable $matchCallback, ?array $currentData = null): ?array { if ($currentData === null) { $currentData = $this->_data; } foreach ($currentData as $item) { if (is_array($item)) { // 先检查当前项是否符合匹配条件 if ($matchCallback($item)) { return $item; } // 不符合则递归遍历子项 $foundItem = $this->findMenuItem($matchCallback, $item); if ($foundItem !== null) { return $foundItem; } } } return null; } // 使用示例:查找cost大于5的菜单项 $expensiveItem = $menu->findMenuItem(function($item) { return isset($item['cost']) && $item['cost'] > 5; }); print_r($expensiveItem);
这样不管你需要什么匹配规则,只需要传入对应的回调函数就行,非常灵活。
内容的提问来源于stack exchange,提问作者Артём Андреев
相关产品推荐
相关产品推荐

