递归函数和多维数组

时间:2013-01-31 11:06:46

标签: php arrays multidimensional-array

如果我传递了一个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的单维数组。例如。

从前一个数组中,如果我传递id为1,我希望函数返回1,2,因为2是子元素的id元素。因此,如果我通过它2,它应该只返回2,因为它没有任何孩子。

我希望你理解我,谢谢你,如果你能帮助我......

请注意,这可以是无限制的,这意味着每个父类别可以具有无限的子类别或子类别。

1 个答案:

答案 0 :(得分:2)

基本上有两个问题需要解决:

  1. 在整个数组中搜索要从ID开始的给定ID。
  2. 在找到ID后从孩子们那里获取所有ID。
  3. 这样可行:

    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]
    

    Iterators将使您的数组完全可遍历。这意味着,您可以foreach覆盖整个阵列,就像它是扁平阵列一样。通常情况下,它只会返回叶子(1,0,0,Shirts,...),但由于我们给它SELF_FIRST选项,它也会返回持有叶子的数组。尝试将var_dump放在foreach中以查看。

    换句话说,这个

    foreach ($iterator as $val) {
    

    将遍历数组中的每个值。

    if (is_array($val) && isset($val['id']) && $val['id'] === $id) {
    

    此行仅考虑数组并检查您传递给findById函数的ID。如果存在,则将ID添加到将由函数返回的数组中。这将解决问题1:找到从哪里开始。

    if (isset($val['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。