【问题标题】:Recursion with multidimensional array多维数组递归
【发布时间】:2017-12-28 12:21:03
【问题描述】:

我已经为此工作了很长时间,并且可以按我的意愿工作,但我认为有更简单的解决方案。

到目前为止,我得到了这个:

$menu = array(
    0 => (object) array(
        'cat_id'   => 1,
        'cat_parent' => 0,
        'cat_name' => 'domov',
        'cat_href' => 'domov',
        'cat_subcategories' => array()
    ),
    1 => (object) array(
        'cat_id'   => 2,
        'cat_parent' => 0,
        'cat_name' => 'clanky',
        'cat_href' => 'clanky',
        'cat_subcategories' => array(
            0 => (object) array(
                'cat_id'   => 9,
                'cat_parent' => 2,
                'cat_name' => 'apple clanky',
                'cat_href' => 'apple',
                'cat_subcategories' => array(
                    0 => (object) array(
                        'cat_id'   => 11,
                        'cat_parent' => 9,
                        'cat_name' => 'iphone clanky',
                        'cat_href' => 'iphone',
                        'cat_subcategories' => array()
                    ),
                    1 => (object) array(
                        'cat_id'   => 12,
                        'cat_parent' => 9,
                        'cat_name' => 'macbook clanky',
                        'cat_href' => 'macbook',
                        'cat_subcategories' => array()
                    )
                )
            ),
            1 => (object) array(
                'cat_id'   => 10,
                'cat_parent' => 2,
                'cat_name' => 'microsoft clanky',
                'cat_href' => 'microsoft',
                'cat_subcategories' => array()
            ),
        )
    ),
    2 => (object) array(
        'cat_id'   => 3,
        'cat_parent' => 0,
        'cat_name' => 'produkty',
        'cat_href' => 'produkty',
        'cat_subcategories' => array()
    ),
    3 => (object) array(
        'cat_id'   => 4,
        'cat_parent' => 0,
        'cat_name' => 'vyrobcovia',
        'cat_href' => 'vyrobcovia',
        'cat_subcategories' =>
            array(
                0 => (object) array(
                    'cat_id'   => 5,
                    'cat_parent' => 4,
                    'cat_name' => 'apple',
                    'cat_href' => 'apple',
                    'cat_subcategories' => array(
                        0 => (object) array(
                            'cat_id'   => 7,
                            'cat_parent' => 5,
                            'cat_name' => 'iphone',
                            'cat_href' => 'iphone',
                            'cat_subcategories' => array()
                        ),
                        1 => (object) array(
                            'cat_id'   => 8,
                            'cat_parent' => 5,
                            'cat_name' => 'macbook',
                            'cat_href' => 'macbook',
                            'cat_subcategories' => array()
                        )
                    )
                ),
                1 => (object) array(
                    'cat_id'   => 6,
                    'cat_parent' => 4,
                    'cat_name' => 'microsoft',
                    'cat_href' => 'microsoft',
                    'cat_subcategories' => array()
                ),
            )
    ),
);
function generate_menu($menu, $level = 1, $tmp_array = array())
{
    foreach($menu as $key => $c)
    {
        $menu_item = get_menu_elements($c, $level);
        $tmp_array = array_replace_recursive($tmp_array, $menu_item);

        foreach($c->cat_subcategories as $_key => $_c)
        {
            $menu_item = get_menu_elements($_c, $level+1);
            $tmp_array = array_replace_recursive($tmp_array, $menu_item);

            foreach($_c->cat_subcategories as $__key => $__c)
            {
                $menu_item = get_menu_elements($__c, $level+2);
                $tmp_array = array_replace_recursive($tmp_array, $menu_item);
            }

        }
    }

    return $tmp_array;
}

function get_menu_elements($c, $level = 1)
{

    $level_var   = "level_".($level);


    $output = array(
        $level_var => array()
    );



    $output[$level_var][$c->cat_id] = array(
        'parent' => $c->cat_parent,
        'html'   => $c->cat_name
    );

    return $output;

}

最后我应该有一个多维数组:

array(3) {
  ["level_1"]=>
  array(4) {
    [1]=>
    array(2) {
      ["parent"]=>
      int(0)
      ["html"]=>
      string(5) "domov"
    }
    [2]=>
    array(2) {
      ["parent"]=>
      int(0)
      ["html"]=>
      string(6) "clanky"
    }
    [3]=>
    array(2) {
      ["parent"]=>
      int(0)
      ["html"]=>
      string(8) "produkty"
    }
    [4]=>
    array(2) {
      ["parent"]=>
      int(0)
      ["html"]=>
      string(10) "vyrobcovia"
    }
  }
  ["level_2"]=>
  array(4) {
    [9]=>
    array(2) {
      ["parent"]=>
      int(2)
      ["html"]=>
      string(12) "apple clanky"
    }
    [10]=>
    array(2) {
      ["parent"]=>
      int(2)
      ["html"]=>
      string(16) "microsoft clanky"
    }
    [5]=>
    array(2) {
      ["parent"]=>
      int(4)
      ["html"]=>
      string(5) "apple"
    }
    [6]=>
    array(2) {
      ["parent"]=>
      int(4)
      ["html"]=>
      string(9) "microsoft"
    }
  }
  ["level_3"]=>
  array(4) {
    [11]=>
    array(2) {
      ["parent"]=>
      int(9)
      ["html"]=>
      string(13) "iphone clanky"
    }
    [12]=>
    array(2) {
      ["parent"]=>
      int(9)
      ["html"]=>
      string(14) "macbook clanky"
    }
    [7]=>
    array(2) {
      ["parent"]=>
      int(5)
      ["html"]=>
      string(6) "iphone"
    }
    [8]=>
    array(2) {
      ["parent"]=>
      int(5)
      ["html"]=>
      string(7) "macbook"
    }
  }
}

我想打印多级菜单递归。我让它使用这段代码,但在函数 generate_menu 中,我不得不为 cat_subcategories 使用 3 个 foreach 循环。当我像这样使用递归时:

function generate_menu($menu, $level = 1, $tmp_array = array())
{
    foreach($menu as $key => $c)
    {
        $menu_item = get_menu_elements($c, $level);
        $tmp_array = array_replace_recursive($tmp_array, $menu_item);

        if (!empty($c->cat_subcategories)) generate_menu($c->cat_subcategories, $level + 1, $tmp_array);
    }

    return $tmp_array;
}

我在输出中只有“level_1”

我现在得到的输出和我想要的一样我只是想简化多个 foreach()

等等。基本上

level_1 - $menu 的第一个循环 level_2 - cat_subcategories 循环 level_3 - cat_subcategories 项的 cat_subcategories 循环

【问题讨论】:

  • 请为示例输入提供所需的输出。目前尚不清楚您期望.......level_1level_2level_3 之后是什么。另外,get_menu_elements 是什么?
  • 已编辑,该函数获取带有菜单模板的 html 文件,而我基本上只是在 html 中解析数据库中的数据。这个结构正在工作我只是发现 generate_menu 中的那些循环是不必要的,我认为它们可能会以某种方式被简化
  • 我试图理解输出,但我立即想知道为什么domov 不会出现在您想要的输出中。也许我很天真,但是那个输出只是你想要的一部分吗?如果是这样,你能多加一点吗?如果可以的话,我会运行你的代码,但我没有 get_level_templates
  • 是的,这只是我没有随身携带代码的一部分。我编辑了代码,以便您可以运行它还包括整个输出

标签: php arrays recursion multidimensional-array


【解决方案1】:

您基本上需要在菜单树中执行广度优先遍历。为此,我建议使用迭代函数而不是递归函数,因为后者更适合深度优先遍历。

函数如下:

function generate_menu($menu) {
    $result = [];

    $level = 1;
    while (count($menu)) {
        $queue = [];
        $items = [];
        foreach($menu as $cat) {
            $items[$cat->cat_id] = [
                "parent" => $cat->cat_parent,
                "html" => $cat->cat_name
            ];
            $queue = array_merge($queue, $cat->cat_subcategories);
        }
        $result["level_$level"] = $items;
        $level++;
        $menu = $queue;
    }
    return $result;
}

查看它在eval.in 上运行。

当这个函数遍历树的顶层时,它将所有的孩子收集到$queue。一旦将顶层转换为输出(在level_1 键中),该队列将具有所有第二级条目。然后将其移至$menu,并重复该过程,但现在使用level_2。这一直持续到达到不再找到条目的级别。

【讨论】:

  • 谢谢我正在考虑先收集顶级项目,但不知道如何处理子类别:D 谢谢
【解决方案2】:

我前段时间做了这个功能。它可以帮助你。

我有一个数组,其中 $arr[actual item][parental id]

function getChild($id, $result, $count) {
    for( $i = 0; $i < sizeof($result); $i ++) {
        if( $result[$i][2] == $id) {
            getChild($result[$i][0], $result, $count + 1);
        }
    }
}

编辑

在我的例子中,一维数组中的所有项目,但具有 n 维数组的层次结构取决于父母 ID。

【讨论】:

  • 不是我的情况,我只需要编辑我的代码,所以我不必使用 3 个循环但递归因为我想使用我的模板
【解决方案3】:

打印菜单代码

此代码适用于 N 个层次结构

 static function printAllCategoriesAsCheckbox($arr, $d=0){

    $htmlString = "";

    if (is_array($arr)){
        foreach($arr as $category){

            $htmlString = $htmlString . '<div><input style="margin-left: ' . 30*$d . 'px;" value="'.$category->id.'" class="category-input" type="checkbox" name="category_id[]">';

            $htmlString = $htmlString . ' <label for="category_'.$category->id.'">' . $category->name . '</label></div>';


            if (is_array($category['childs'])){
                $htmlString = $htmlString . ItemCategory::printAllCategoriesAsCheckbox($category['childs'], $d+1);
            }
        }
    }

    return $htmlString;
}

【讨论】:

  • 不是我的情况,我只需要编辑我的代码,所以我不必使用 3 个循环但递归因为我想使用我的模板
  • @DeiForm 它完全适合您的模板。我看到了你的输入。你不需要 3 个循环
  • 我不希望字符串作为退休值
猜你喜欢
  • 2017-11-28
  • 2019-02-20
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
相关资源
最近更新 更多