递归函数和多维数组
Posted
技术标签:
【中文标题】递归函数和多维数组【英文标题】:Recursive functions and multidimensional arrays 【发布时间】:2013-01-15 11:07:53 【问题描述】:如果我传递一个 id,我如何从所有子元素中获取 ['id']。
这是我的数组...
$array = Array
(
'0' => Array
(
'id' => 1,
'parent_id' => 0,
'order_pos' => 0,
'title' => 'Shirts',
'childs' => Array
(
'0' => Array
(
'id' => 2,
'parent_id' => 1,
'order_pos' => 0,
'title' => 'Small Shirts',
)
)
),
'1' => Array
(
'id' => 3,
'parent_id' => 0,
'order_pos' => 0,
'title' => 'Cameras'
)
);
如果我编写 i 函数并传递一个 id 为 1 的变量,有人可以告诉我如何返回一个仅包含所有子元素的 id 的一维数组。例如。
从前面的数组中,如果我传递 1 的 id,我希望函数返回 1、2,因为 2 是子元素的 id 元素。所以如果我通过它 2,它应该只返回 2,因为它没有任何孩子。
希望你能理解我,如果你能帮助我,谢谢...
注意,这可以是无限的,这意味着每个父类别可以有无限的子类别或子类别。
【问题讨论】:
如果在多个级别上存在相同的 ID 怎么办,例如在您的示例中,ID 为 2 的孩子可以有另一个 ID 为 3 的孩子。还有 ID 为 3 的***元素。这会发生吗?那么输出应该是什么。 为什么parent_id
键出现在子元素中? this的值可以和父元素的ID不同吗?
@Gordon 不,这不可能发生。 id 是唯一的,数组是从 id 是关键字段的数据库中构建的。
@One Trick Pony 存在是因为数组是从数据库表构建的,它有id、parent_id、name,所以它从数据库表构建多维数组。
【参考方案1】:
基本上有两个问题需要解决:
-
在整个数组中搜索给定 ID 的起始位置。
一旦找到 ID,就从孩子们那里提取所有 ID。
这可行:
function findIds(array $array, $id)
$ids = array();
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $val)
if (is_array($val) && isset($val['id']) && $val['id'] === $id)
$ids[] = $val['id'];
if (isset($val['childs']))
array_walk_recursive(
$val['childs'],
function($val, $key) use (&$ids)
if ($key === 'id')
$ids[] = $val;
);
return $ids;
print_r( findIds($array, 1) ); // [1, 2]
print_r( findIds($array, 2) ); // [2]
print_r( findIds($array, 3) ); // [3]
迭代器将使您的数组完全可遍历。这意味着,您可以在整个阵列上foreach
,就像它是一个平面阵列一样。通常,它只会返回叶子 (1, 0, 0, Shirts, ...),但由于我们给了它SELF_FIRST
选项,它也会返回包含叶子的数组。尝试在 foreach 中添加 var_dump
以查看。
换句话说,这个
foreach ($iterator as $val)
将遍历数组中的每个值。
if (is_array($val) && isset($val['id']) && $val['id'] === $id)
这一行将只考虑数组并检查您传递给findById
函数的ID。如果存在,则将 ID 添加到函数将返回的数组中。这样就可以解决问题 1:找到从哪里开始。
if (isset($val['childs']))
如果数组有一个“childs”项(它应该是childs btw),它将递归地从该项中获取所有ID并将它们添加到返回的数组中:
array_walk_recursive(
$val['childs'],
function($val, $key) use (&$ids)
if ($key === 'id')
$ids[] = $val;
);
array_walk_recursive
接受一个数组(第一个参数)并将叶子的值和键传递给回调函数(第二个参数)。回调函数仅检查叶子是否是 ID 值,然后将其添加到返回数组中。如您所见,我们使用的是对返回数组的引用。这是因为使用use ($ids)
会在闭包范围内创建数组的副本,而我们需要真正的数组以便向其中添加项目。这将解决问题 2:添加所有子 ID。
【讨论】:
谢谢伙计,不幸的是它似乎没有工作......我认为它可能在这条线上: if (is_array($val) && isset($val['id']) && $val ['id'] === $id) 我认为如果我在这里删除一个等号 $val['id'] === $id to $val['id'] == $id...顺便说一下@gordon,第三个等号是什么意思?我知道单是设置,双是比较,什么是3? @Codecube 看这里***.com/questions/1117967。它会检查身份,因此当您为 $id 插入“2”而不是 2 时,它不会找到任何东西,因为“2”与 2 的类型不同(字符串与整数)。 啊我明白...很好,不知道 php 可以做到这一点。只有 1 个问题,如果我把第三个等号放在它不会工作.. 如果我删除它完全有效我希望它如何工作...有趣...您还可以解释您编写的代码吗,例如解释为什么要编写某些代码行,我讨厌只是复制和粘贴,我希望能够重新以后写出来,看懂了.... @Codecube 我已经添加了解释。您还可以在eval.in/8141 上看到演示,显示代码按给定的方式工作。如果您必须使用==
,您可能不会为 $id 传递整数。以上是关于递归函数和多维数组的主要内容,如果未能解决你的问题,请参考以下文章