我有像这样的 N 级阵列
$array = [
[
'id' => 67941,
'parent_id' => 0,
'name' => 'Requirement',
'children' => [
[
'id' => 67942,
'parent_id' => 67941,
'name' => 'Sub Requirement',
'children' => [
[
'id' => 67943,
'parent_id' => 67942,
'name' => 'Sub Sub Requirement',
],
],
],
],
],
//...
];
我想搜索 67943——它位于数组的第 3 个索引级别(实际上是第 5 个级别)。我可以使用
array_walk_recursive()
来查找该值是否存在,但我需要收集导致该值的索引的完整路径,例如$array[0][0][0]['id']
.
我不能对关卡进行硬编码,我需要一个可以在超过 100 个关卡的阵列上工作的解决方案。
我对 RecursiveIteratorIterator 类或其表兄弟没有太多经验,但我能够修改this answer以满足您的条件要求。
遍历数组时,如果键是“children”,则不要缓存键。
如果该值为搜索值,则捕获key的当前路径并打破循环。
我不明白你为什么想要
$array[0][0][0]['id']
的返回值,所以我只返回一个包含键的平面数组。
代码:(演示)
$needle = 67943;
$ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
$result = null;
foreach ($ritit as $leafValue) {
$path = [];
foreach (range(0, $ritit->getDepth()) as $depth) {
$obj = $ritit->getSubIterator($depth);
$key = $obj->key();
if ($key !== 'children') {
$path[] = $key;
}
if ($obj->current() === $needle) {
$result = $path;
break 2;
}
}
}
var_export($result);
输出:
array (
0 => 0,
1 => 0,
2 => 0,
3 => 'id',
)
这样可以避免使用递归函数,并以广度优先的方式返回匹配的数组。根据您的需要,可以修改它以返回路径的字符串表示形式。
function findNode(array $nodes, $searchValue) {
while (!empty($nodes)) {
$node = array_pop($nodes);
if (isset($node['id']) && ($node['id'] == $searchValue)) {
// found
return $node;
}
// add any children to the list of nodes to be searched
if (!empty($node['children']) && is_array($node['children'])) {
$nodes = array_merge($node['children'], $nodes);
}
}
// not found
return null;
}
$foundNode = findNode($myArray, 67943);