【问题标题】:Create nested list from Multidimensional Array从多维数组创建嵌套列表
【发布时间】:2012-10-07 18:44:19
【问题描述】:

我在 PHP 中有一个数组,如下所示:

array (
    [0] => array (
        [id] => 1
        [title] => "Title 1"
        [parent_id] => NULL
        [depth] => 0
    )
    [1] => array (
        [id] => 2
        [title] => "Title 2"
        [parent_id] => NULL
        [depth] => 0
    )
    [2] => array (
        [id] => 3
        [title] => "Title 3"
        [parent_id] => 2
        [depth] => 1
    )
    [3] => array (
        [id] => 4
        [title] => "Title 4"
        [parent_id] => 2
        [depth] => 1
    )
    [4] => array (
        [id] => 5
        [title] => "Title 5"
        [parent_id] => NULL
        [depth] => 0
    )
    [5] => array (
        [id] => 6
        [title] => "Title 6"
        [parent_id] => 4
        [depth] => 2
    )
)

我想要做的是遍历这个数组并从中创建一个嵌套的<ol> 列表。所以结果应该是这样的:

<ol>
    <li>Title 1</li> // id = 1
    <li>Title 2</li> // id = 2
    <ol>
        <li>Title 3</li> // id = 3 -> parent_id = 2
        <li>Title 4</li> // id = 4 -> parent_id = 2
        <ol>
            <li>Title 6</li> // id = 6 -> parent_id = 4
        </ol>
    </ol>
    <li>Title 5</li> // id = 5
</ol>

我一直在想办法如何完成这项工作。但到目前为止,每一次尝试都失败了……

任何人知道如何从这样的数组创建这样一个嵌套的&lt;ol&gt; 列表吗?

请注意,我对给定数据没有任何控制权。我只是调用一个 API,它返回 json 数据,我将其转换为一个数组。这个数组看起来和我描述的一模一样。

【问题讨论】:

  • 表面上看起来很简单,但我认为您仍然缺乏信息来获得适合您情况的最佳答案。首先,你是如何得到数组的?它来自数据库吗?是否有可能以不同的方式存储它,还是你被困在这种方式中?深度是否保证(现在或将来)不会超过 1 或 2,或者您是否计划进行不确定数量的子级别?添加或删除类别的频率如何?我建议您查看mikehillyer.com/articles/managing-hierarchical-data-in-mysql,因为嵌套模型可能更符合您的需求。

标签: php arrays


【解决方案1】:

你应该使用递归

首先是'php'语法中的数组:

<?php
$a=array (
    '0' => array (
        'id' => 1,
        'title' => "Title 1",
        'parent_id' => 'NULL',
        'depth' => 0
    ),
    '1' => array (
        'id' => 2,
        'title' => "Title 2",
        'parent_id' => 'NULL',
        'depth' => 0
    ),
    '2' => array (
        'id' => 3,
        'title' => "Title 3",
        'parent_id' => 2,
        'depth' => 1
    ),
    '3' => array (
        'id' => 4,
        'title' => "Title 4",
        'parent_id' => 2,
        'depth' => 1
    ),
    '4' => array (
        'id' => 5,
        'title' => "Title 5",
        'parent_id' => 'NULL',
        'depth' => 0
    ),
    '5' => array (
        'id' => 6,
        'title' => "Title 6",
        'parent_id' => 4,
        'depth' => 0
    )
);

这里是代码

$level = 'NULL';

function r( $a, $level) {
   $r = "<ol>";
   foreach ( $a as $i ) {
       if ($i['parent_id'] == $level ) {
          $r = $r . "<li>" . $i['title'] . r( $a, $i['id'] ) . "</li>";
       }
   }
   $r = $r . "</ol>";
   return $r;
}

print r( $a, $level );

?>

结果

<ol><li>Title 1<ol></ol></li><li>Title 2<ol><li>Title 3<ol>
</ol></li><li>Title 4<ol><li>Title 6<ol></ol></li></ol></li></ol></li><li>Title 5
<ol></ol></li></ol>
  1. 标题 1\n
    1. 标题 2\n
      1. 标题 3\n
        1. 标题 4\n
          1. 标题 6\n
        2. 标题 5\n

          检查后作为解决方案编辑

          为了避免空叶子:

          function r( $a, $level) {
             $r = '' ;
             foreach ( $a as $i ) {
                 if ($i['parent_id'] == $level ) {
                    $r = $r . "<li>" . $i['title'] . r( $a, $i['id'] ) . "</li>";
                 }
             }
             return ($r==''?'':"<ol>". $r . "</ol>");
          }
          

          【讨论】:

            【解决方案2】:

            你可以试试下面的

            $array = array (
                "0" => array (
                    "id" => 1,
                    "title" => "Title 1",
                    "parent_id" => NULL,
                    "depth" => 0
                ),
                "1" => array (
                    "id" => 2,
                    "title" => "Title 2",
                    "parent_id" => NULL,
                    "depth" => 0
                ),
                "2" => array (
                    "id" => 3,
                    "title" => "Title 3",
                    "parent_id" => 2,
                    "depth" => 1
                ),
                "3" => array (
                    "id" => 4,
                    "title" => "Title 4",
                    "parent_id" => 2,
                    "depth" => 1
                ),
                "4" => array (
                    "id" => 5,
                    "title" => "Title 5",
                    "parent_id" => NULL,
                    "depth" => 0
                ),
                "5" => array (
                    "id" => 6,
                    "title" => "Title 6",
                    "parent_id" => 4,
                    "depth" => 0
                )
            );
            
            echo(make($array));
            

            输出

            <ol>
                <li>Title 1</li>
                <li>Title 2</li>
                <ol>
                    <li>Title 3</li>
                    <li>Title 4</li>
                    <ol>
                        <li>Title 6</li>
                    </ol>
                </ol>
                <li>Title 5</li>
            </ol>
            

            使用的功能

            function make(array $array, $no = 0) {
                $child = hasChildren($array, $no);
                if (empty($child))
                    return "";
                $content = "<ol>\n";
                foreach ( $child as $value ) {
                    $content .= sprintf("\t<li>%s</li>\n", $value['title']);
                    $content .= make($array, $value['id']);
                }
                $content .= "</ol>\n";
                return $content;
            }
            
            function hasChildren($array, $id) {
                return array_filter($array, function ($var) use($id) {
                    return $var['parent_id'] == $id;
                });
            }
            

            See Live Demo

            【讨论】:

            • 很好的答案,谢谢。你能告诉我假设数组元素没有depth 键(因为我没有)我们如何设置最大深度。我想我们需要$level = 0;$max_level = 3。但是如何将它们放在你的函数中呢?
            • @Baba,他是个好地方。希望你有时间来回顾一下。
            【解决方案3】:

            以下数组:

            Array
            (
                [0] => Content
                [1] => Array
                    (
                        [0] => International
                        [1] => Array
                            (
                                [0] => Mexico
                                [1] => Array
                                    (
                                        [0] => Tamaulipas
                                    )
            
                                [2] => USA
                            )
            
                    )
            
            )
            

            使用此功能:

            function r($element) {
                foreach ($element as $value) {
                    if (!is_array($value)) {
                        echo "<li>";
                        echo $value;
                    } else {
                        echo "<ul>";
                        r($value);
                        echo "</li>";
                        echo "</ul>";
                    }
                }
            }
            

            PHP 代码:

            echo "<ul>";
            r($array);
            echo "</ul>";
            

            返回:

            <ul>
                <li>Public</li>
                <li>User</li>
                <li>Content
                    <ul>
                        <li>International
                            <ul>
                                <li>Mexico
                                    <ul>
                                        <li>Tamaulipas</li>
                                    </ul>  
                                </li>
                                <li>USA</li>
                            </ul>
                        </li>
                    </ul>
                </li>
            </ul>
            

            【讨论】:

              猜你喜欢
              • 2014-02-02
              • 2013-10-19
              • 1970-01-01
              • 1970-01-01
              • 2016-12-10
              • 2023-04-07
              • 2015-09-02
              • 1970-01-01
              相关资源
              最近更新 更多