递归函数和多维数组

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 传递整数。

以上是关于递归函数和多维数组的主要内容,如果未能解决你的问题,请参考以下文章

PHP递归函数将多维数组转换为xml

从数据库结果生成多维数组的递归函数

递归函数输出一个狂野的多维数组,希望它深一层

使用递归函数获取多维php数组的新值和键

在 PHP 中递归创建多维数组

如何在 PHP 中循环遍历多维数组并按名称递归删除键?