【问题标题】:Search in multidimensional array recursive for key/value pair and return the path在多维数组中递归搜索键/值对并返回路径
【发布时间】:2014-08-01 18:56:42
【问题描述】:

我正在研究导航结构。 我正在使用父模型,所以我将所有子导航节点放入一个数组并将它们附加到父导航。

数组结构如下:

$navigation = array(
    0 =>
        array(
            'id' => '2',
            'parent_id' => '0',
            'name' => 'abouts us',
            'subNavigation' =>
                array(
                    0 => array(
                        'id' => '3',
                        'parent_id' => '2',
                        'name' => 'Foo',
                        'subNavigation' =>
                            array(
                                0 => array(
                                    'id' => '4',
                                    'parent_id' => '3',
                                    'name' => 'test',
                                    'subNavigation' =>
                                        array(),
                                ),
                                1 => array(
                                    'id' => '5',
                                    'parent_id' => '3',
                                    'name' => 'bar',
                                    'subNavigation' =>
                                        array(),
                                ),
                            ),
                        ),
                ),
        ),
    1 =>
        array(
            'id' => '6',
            'parent_id' => '0',
            'name' => 'Foobar',
            'subNavigation' =>
                array(
                    0 => array(
                        'id' => '7',
                        'parent_id' => '6',
                        'name' => 'ASDF',
                        'subNavigation' =>
                            array(),
                    ),
                ),
        ),
);

现在我想搜索一个导航 ID,例如 ID = 5 (Navigation-Name = bar),结果应该是这个子导航的数组。

结果:

$result = array(
    0 =>
        array(
            'id' => '2',
            'parent_id' => '0',
            'name' => 'abouts us',
            'subNavigation' =>
                array(
                    0 => array(
                        'id' => '3',
                        'parent_id' => '2',
                        'name' => 'Foo',
                        'subNavigation' =>
                            array(
                                0 => array(
                                    'id' => '5',
                                    'parent_id' => '3',
                                    'name' => 'bar',
                                    'subNavigation' =>
                                        array(),
                                ),
                            ),
                    ),
                ),
        ),
);

最快的方法是什么?哪个递归函数可以完成这项工作?

编辑: 我编辑了导航节点 5 的 parent_id ...哪里是错误的 parent_id

【问题讨论】:

    标签: php recursion multidimensional-array


    【解决方案1】:

    非常有趣的问题。这是一个解决方案:

    function search($navitation_tree, $id, $temp_branch = array()) {
        for ($i = 0; $i < sizeof($navitation_tree); $i++) {
            $nav_element = $navitation_tree[$i];
    
            if($nav_element['parent_id'] === '0') {
                $temp_branch = array();
            } else if($i > 0) {
                for ($y = 0; $y < 1; $y++) {
                    array_pop($temp_branch);
                }
            }
    
            $cloned_nav_element = array('id' => $nav_element['id'],
                                        'parent_id' => $nav_element['parent_id'],
                                        'name' => $nav_element['name'],
                                        'subNavigation' => array());
            $temp_branch[] = $cloned_nav_element;
    
            if($nav_element['id'] === $id) {
                return $temp_branch;
            }
    
            if(sizeof($nav_element['subNavigation'] > 0)) {
                $result = search($nav_element['subNavigation'], $id, $temp_branch);
            }
    
            if($result != null) {
    
                return $result;
            }
        }
    }
    
    function getNavigationBranch($navitation_tree, $id) {
        $branch = search($navitation_tree, $id);
    
        if($branch !== null) {
            $final_nav_element = array();
            foreach($branch as $temp_nav_element) {
                if(empty($final_nav_element)) {
                    $final_nav_element = array(array_pop($branch));
                } else {
                    $temp_nav_element = array_pop($branch);
                    $temp_nav_element['subNavigation'] = $final_nav_element;
                    $final_nav_element = array($temp_nav_element);
                }
            }
    
            return $final_nav_element;
        }
    }
    
    $result = getNavigationBranch($navigation, '5');
    

    search 函数在导航树中执行depth-first search (DFS)。一旦找到所需的 id,它就会将路径(由导航元素的有序数组表示)返回到 getNavigationBranch,它将数据重新构造为您在问题中请求的格式,并返回它们(它将如果没有找到 id,则返回null

    顺便说一句,虽然 DFS 在大图中搜索时会出现问题,但我认为它适用于(如果不是全部的话)导航树的大多数情况。

    为了测试它,我使用了以下数据:

    $navigation = array(
        0 =>
            array(
                'id' => '2',
                'parent_id' => '0',
                'name' => 'abouts us',
                'subNavigation' =>
                    array(
                        0 => array(
                            'id' => '3',
                            'parent_id' => '2',
                            'name' => 'Foo',
                            'subNavigation' =>
                                array(
                                    0 => array(
                                        'id' => '4',
                                        'parent_id' => '3',
                                        'name' => 'test',
                                        'subNavigation' =>
                                            array(),
                                    ),
                                    1 => array(
                                        'id' => '5',
                                        'parent_id' => '3',
                                        'name' => 'bar',
                                        'subNavigation' =>
                                            array(),
                                    ),
                                ),
                            ),
                        1 => array(
                            'id' => '8',
                            'parent_id' => '2',
                            'name' => 'Foo',
                            'subNavigation' =>
                                array(
                                    0 => array(
                                        'id' => '9',
                                        'parent_id' => '8',
                                        'name' => 'test',
                                        'subNavigation' =>
                                            array(),
                                    ),
                                    1 => array(
                                        'id' => '10',
                                        'parent_id' => '8',
                                        'name' => 'bar',
                                        'subNavigation' =>
                                            array(),
                                    ),
                                ),
                            ),
                        2 => array(
                            'id' => '11',
                            'parent_id' => '2',
                            'name' => 'Foo',
                            'subNavigation' =>
                                array(
                                    0 => array(
                                        'id' => '12',
                                        'parent_id' => '8',
                                        'name' => 'test',
                                        'subNavigation' =>
                                            array(),
                                    ),
                                    1 => array(
                                        'id' => '13',
                                        'parent_id' => '8',
                                        'name' => 'bar',
                                        'subNavigation' =>
                                            array(),
                                    ),
                                ),
                            ),
                    ),
            ),
        1 =>
            array(
                'id' => '6',
                'parent_id' => '0',
                'name' => 'Foobar',
                'subNavigation' =>
                    array(
                        0 => array(
                            'id' => '7',
                            'parent_id' => '6',
                            'name' => 'ASDF',
                            'subNavigation' =>
                                array(),
                        ),
                    ),
            ),
    );
    

    以下是几个测试结果:

    $result = getNavigationBranch($navigation, '5');
    var_dump($result);
    

    以上产生:

    array(1) {
      [0]=>
      array(4) {
        ["id"]=>
        string(1) "2"
        ["parent_id"]=>
        string(1) "0"
        ["name"]=>
        string(9) "abouts us"
        ["subNavigation"]=>
        array(1) {
          [0]=>
          array(4) {
            ["id"]=>
            string(1) "3"
            ["parent_id"]=>
            string(1) "2"
            ["name"]=>
            string(3) "Foo"
            ["subNavigation"]=>
            array(1) {
              [0]=>
              array(4) {
                ["id"]=>
                string(1) "5"
                ["parent_id"]=>
                string(1) "3"
                ["name"]=>
                string(3) "bar"
                ["subNavigation"]=>
                array(0) {
                }
              }
            }
          }
        }
      }
    }
    

    还有一个:

    $result = getNavigationBranch($navigation, '13');
    var_dump($result);
    

    以上产生:

    array(1) {
      [0]=>
      array(4) {
        ["id"]=>
        string(1) "2"
        ["parent_id"]=>
        string(1) "0"
        ["name"]=>
        string(9) "abouts us"
        ["subNavigation"]=>
        array(1) {
          [0]=>
          array(4) {
            ["id"]=>
            string(2) "11"
            ["parent_id"]=>
            string(1) "2"
            ["name"]=>
            string(3) "Foo"
            ["subNavigation"]=>
            array(1) {
              [0]=>
              array(4) {
                ["id"]=>
                string(2) "13"
                ["parent_id"]=>
                string(1) "8"
                ["name"]=>
                string(3) "bar"
                ["subNavigation"]=>
                array(0) {
                }
              }
            }
          }
        }
      }
    }
    

    【讨论】:

    • 感谢您的回答。这个片段效果很好!您对大型导航树的性能有何看法
    • @JuKe 请定义大型导航树的含义(例如它们可能包含多少个节点)。
    猜你喜欢
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 2017-11-16
    相关资源
    最近更新 更多