【问题标题】:Flat array to multidimensional array平面数组到多维数组
【发布时间】:2012-11-27 10:08:21
【问题描述】:

我在 WP 中有一个包含导航菜单项的平面数组。每个项目都知道它的父母,但他们似乎都不知道他们是否有孩子。

            Array
(
    [0] => stdClass Object
        (
            [ID] => 22
            [menu_item_parent] => 0
        )
    [1] => stdClass Object
        (
            [ID] => 108
            [menu_item_parent] => 22
        )
    [2] => stdClass Object
        (
            [ID] => 117
            [menu_item_parent] => 108
        )
    [3] => stdClass Object
        (
            [ID] => 118
            [menu_item_parent] => 108
        )
    [4] => stdClass Object
        (
            [ID] => 106
            [menu_item_parent] => 22
        )
    [5] => stdClass Object
        (
            [ID] => 119
            [menu_item_parent] => 106
        )
    [6] => stdClass Object
        (
            [ID] => 120
            [menu_item_parent] => 106
        )
    [7] => stdClass Object
        (
            [ID] => 23
            [menu_item_parent] => 0
        )
)

我尝试了几种不同的方法(并且每次都硬编码不理想的值)来使用条件逻辑来处理它,但我一直把自己编码成一团糟。如何遍历数组以产生这样的结果?

<ul>
    <li>22
        <ul class="child">
            <li>108
                <ul class="grandchild">
                    <li>117</li>
                    <li>118</li>
                </ul>
            </li>
            <li>106
                <ul class="grandchild">
                    <li>119</li>
                    <li>120</li>
                </ul>
            </li>           
        </ul>
    </li>
    <li>23</li>
</ul>

【问题讨论】:

  • 你的源数组是否总是从根到节点排序?
  • 是的,这就是 WP 吐出来的方式。
  • 嗯,不,不是@Maerlyn。这与我试图实现的目标完全相反
  • 我认为这是一个合理的问题。我不知道为什么它获得了接近投票。

标签: php


【解决方案1】:

您需要识别节点的子节点,以便您可以将它们放入您需要的结构中。为此,您需要遍历元素并重新组织它们。下面是一个粗略的代码;没测试过。

$new = array();

foreach ($array as $elm)
{
    if ($elm->menu_item_parent != 0)
    {
        foreach($new as $it)
        {
            $found = false;
            if ($it->ID == $elm->menu_item_parent)
            {
                $it->children[] = $elm;
                $found = true; // Found the parent break loop
            } else if (isset($it->children))
            {
                foreach ($it->children as $child)
                {
                    if ($child->ID == $elm->menu_item_parent)
                    {
                        $child->children[] == $elm;
                        $found = true;
                        break;
                    }
                }

                if ($found) break;
            }
        }
    } else {
        $new[] = $elm; // Parent element - add directly
    }
}

数组 $new 现在应该包含带有子节点的元素,您可以对其进行迭代以产生所需的结果。

这通过循环当前数组、识别父节点和它们的子节点并将它们组织起来来工作。只能工作两层;如果你需要更深入,代码可能需要修改以更好地组织它。

【讨论】:

  • 我采用了自己的解决方案,但对输入表示赞成。干杯。
【解决方案2】:

我想从制作单独的父(主)数组和子数组开始(或者我们可以把它做成一个长的多维数组)

foreach($arr AS $value)
{
    if($value->menu_item_parent == 0)
        $parentArr[] = $value->ID;
    else
        $childArr[$value->menu_item_parent][] = $value->ID; 
}

递归函数将有助于获得一点全局解决方案来生成子孙。考虑一下,

$str = '';

echo "<ul>";
foreach($parentArr AS $pValue)
{
    echo '<li>'.$pValue;
        if(in_array($pValue, array_keys($childArr)))
        {
            echo '<ul class="child">';
            $result= childs($pValue); //calling a recursive function (In case one have larger child tree)
            echo $result;
            echo '</ul>';
        }
    echo '</li>';
}
echo '</ul>';

function childs($val)
{
    global $childArr;
    global $str;

    foreach($childArr[$val] AS $cValue)
    {
        $str.= '<li>'.$cValue;

        if(in_array($cValue, array_keys($childArr)))
        {
            $str.= '<ul class="grand_child">';
            childs($cValue);
            $str.= '</ul>';
        }
        $str.= '</li>';
    }

    return $str;
}

必须有比这更好的方法来处理这类问题。

【讨论】:

  • 我采用了自己的解决方案,但对输入表示赞成。干杯。
【解决方案3】:

我最终这样做了:

<?php 
$items = wp_get_nav_menu_items('primary'); // original flat array
foreach ($items as $item) {
    $pages[$item->menu_item_parent][] = $item; // create new array
}
foreach ($pages[0] as $parent) {
    if (isset($pages[$parent->ID])) { // if page has children
        echo '<li>'.$parent->ID;
        echo '<ul class="children">';
        foreach ($pages[$parent->ID] as $child) {
            if (isset($pages[$child->ID])) { // child has children
                echo '<li>'.$child->ID;
                echo '<ul class="grandchildren">';
                foreach ($pages[$child->ID] as $grandchild) {
                    echo '<li>'.$grandchild->ID.'</li>';
                }
                echo '</ul></li>';
            } else {
                echo '<li>'.$child->ID.'</li>'; // child has no children
            }
        }
        echo '</ul></li>';
    } else { // page has no children
        echo '<li>'.$parent->ID.'</li>';
    }
}
?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多