如何从平面数组构建具有无限深度的嵌套 HTML 列表? [英] How can I build a nested HTML list with an infinite depth from a flat array?

查看:54
本文介绍了如何从平面数组构建具有无限深度的嵌套 HTML 列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从格式如下的源数组生成多级 HTML 列表:

/*** id = 唯一 id* parent_id = "id" 表示此项直接嵌套在其下* text = 输出字符串*/$list = 数组(大批('id' =>1、'parent_id' =>0,'文本' =>'1级',), 大批('id' =>2、'parent_id' =>0,'文本' =>'级别 2',), 大批('id' =>3、'parent_id' =>2、'文本' =>'级别 2.1',), 大批('id' =>4、'parent_id' =>2、'文本' =>'级别 2.2',), 大批('id' =>5、'parent_id' =>4、'文本' =>'级别 2.2.1',), 大批('id' =>6、'parent_id' =>0,'文本' =>'级别 3',));

目标是具有无限深度的嵌套

    .上面数组的预期输出是这样的:

    • Level 1
    • Level 2
      • Level 2.1
      • Level 2.2
        • Level 2.2.1
        • ul>
      • 三级

      如果只有数组项有一个名为 child 的键或包含实际子数组的东西,则很容易递归这些并使用如下函数获得所需的输出:

      function makeList($list){echo '
        ';foreach ($list 作为 $item){echo '
      • '.$item['text'];如果 (isset($item['child'])){makeList($item['child']);}echo '</li>';}回声'</ul>';}

      不幸的是,我的情况并非如此 - 源数组的格式无法更改.所以,很久以前我写了这个非常讨厌的函数来实现它,它只能在三个级别上工作(代码是逐字粘贴的,带有原始注释).我知道阅读很长很无聊,请耐心等待:

      function makeArray($links){//输出$nav = array();foreach ($links as $k => $v){//如果没有parent_id,我们可以假设它是一个顶级链接如果(空($v['parent_id'])){$id = isset($v['id']) ?$v['id'] : $k;$nav[$id] = $v;//从原数组中移除未设置($links[$k]);}}//再次循环剩余的链接,//我们可以假设它们都有一个 parent_idforeach ($links as $k => $v){//链接的parent_id在顶级数组中,所以这是一个二级链接//我们已经遍历了每个项目,所以我们知道它们都被考虑在内如果 (isset($nav[$v['parent_id']])){$id = isset($v['id']) ?$v['id'] : $k;//将其作为子项添加到顶级链接$nav[$v['parent_id']]['child'][$id] = $v;//设置一个标记,以便我们知道要循环添加第三级的标记$nav2[$id] = $v;//从数组中删除未设置($links[$k]);}}//第三级的最后一次迭代//此时所有其他链接都已从原始数组中删除foreach ($links as $k => $v){$id = isset($v['id']) ?$v['id'] : $k;//链接的parent_id在二级数组中,所以这是一个三级链接//孤儿将被忽略如果 (isset($nav2[$v['parent_id']])){//这部分很疯狂,随它去吧$nav3 = $nav2[$v['parent_id']]['parent_id'];$nav[$nav3]['child'][$v['parent_id']]['child'][] = $v;}}返回 $nav;}

      这使得数组如下:

      数组('文本' =>'1级''孩子' =>大批(大批('文本' =>'级别 1.2''孩子' =>大批(大批('文本' =>'级别 1.2.1''孩子' =>大批(//等等.),大批('文本' =>'级别 1.2.2''孩子' =>大批(//等等.),)))));

      用法:

      $nav = makeArray($links);makeList($nav);

      <小时>

      我花了很多空闲时间试图解决这个问题,我在这里给出的原始代码仍然是我能够生成的最佳解决方案.

      如果没有那个糟糕的功能(深度限制为 3),并且有无限多个级别,我怎么能做到这一点?有没有更优雅的解决方案?

      解决方案

      打印:

      function printListRecursive(&$list,$parent=0){$foundSome = false;for( $i=0,$c=count($list);$i<$c;$i++ ){if( $list[$i]['parent_id']==$parent ){如果( $foundSome==false ){echo '
        ';$foundSome = true;}echo '<li>'.$list[$i]['text'].'</li>';printListRecursive($list,$list[$i]['id']);}}如果( $foundSome ){回声'</ul>';}}printListRecursive($list);

      创建多维数组:

      function makeListRecursive(&$list,$parent=0){$result = array();for( $i=0,$c=count($list);$i<$c;$i++ ){if( $list[$i]['parent_id']==$parent ){$list[$i]['childs'] = makeListRecursive($list,$list[$i]['id']);$result[] = $list[$i];}}返回 $result;}$result = array();$result = makeListRecursive($list);echo '

      ';var_dump($result);echo '</pre>';

      I'm trying to produce a multi-level HTML list from a source array that is formatted like this:

      /**
       * id = unique id
       * parent_id = "id" that this item is directly nested under
       * text = the output string
       */
      $list = array(
          array(
              'id'        =>  1,
              'parent_id' =>  0,
              'text'      =>  'Level 1',
          ), array(
              'id'        =>  2,
              'parent_id' =>  0,
              'text'      =>  'Level 2',
          ), array(
              'id'        =>  3,
              'parent_id' =>  2,
              'text'      =>  'Level 2.1',
          ), array(
              'id'        =>  4,
              'parent_id' =>  2,
              'text'      =>  'Level 2.2',
          ), array(
              'id'        =>  5,
              'parent_id' =>  4,
              'text'      =>  'Level 2.2.1',
          ), array(
              'id'        =>  6,
              'parent_id' =>  0,
              'text'      =>  'Level 3',
          )
      );
      

      The goal is a nested <ul> with an infinite depth. The expected output of the array above is this:

      • Level 1
      • Level 2
        • Level 2.1
        • Level 2.2
          • Level 2.2.1
      • Level 3

      If only the array items had a key called child or something that contained the actual sub-array, it would be easy to recurse though these and get the desired output with a function like this:

      function makeList($list)
      {
          echo '<ul>';
          foreach ($list as $item)
          {
              echo '<li>'.$item['text'];
              if (isset($item['child']))
              {
                  makeList($item['child']);
              }
              echo '</li>';
          }
          echo '</ul>';
      }
      

      Unfortunately that's not the case for me - the format of the source arrays can't be changed. So, long ago I wrote this very nasty function to make it happen, and it only works up to three levels (code is pasted verbatim with original comments). I know it's a long boring read, please bear with me:

      function makeArray($links)
      {
          // Output
          $nav = array();
      
          foreach ($links as $k => $v)
          {
              // If no parent_id is present, we can assume it is a top-level link
              if (empty($v['parent_id']))
              {
                  $id = isset($v['id']) ? $v['id'] : $k;
      
                  $nav[$id] = $v;
      
                  // Remove from original array
                  unset($links[$k]);
              }
          }
      
          // Loop through the remaining links again,
          // we can assume they all have a parent_id
          foreach ($links as $k => $v)
          {
              // Link's parent_id is in the top level array, so this is a level-2 link
              // We already looped through every item so we know they are all accounted for
              if (isset($nav[$v['parent_id']]))
              {
                  $id = isset($v['id']) ? $v['id'] : $k;
      
                  // Add it to the top level links as a child
                  $nav[$v['parent_id']]['child'][$id] = $v;
      
                  // Set a marker so we know which ones to loop through to add the third level
                  $nav2[$id] = $v;
      
                  // Remove it from the array
                  unset($links[$k]);
              }
          }
      
          // Last iteration for the third level
          // All other links have been removed from the original array at this point
          foreach ($links as $k => $v)
          {
              $id = isset($v['id']) ? $v['id'] : $k;
      
              // Link's parent_id is in the second level array, so this is a level-3 link
              // Orphans will be ignored
              if (isset($nav2[$v['parent_id']]))
              {
                  // This part is crazy, just go with it
                  $nav3 = $nav2[$v['parent_id']]['parent_id'];
                  $nav[$nav3]['child'][$v['parent_id']]['child'][] = $v;
              }
      
          }
      
          return $nav;
      }
      

      This makes an array like:

      array(
          'text' => 'Level 1'
          'child' => array(
              array(
                  'text' => 'Level 1.2'
                  'child' => array(
                      array(
                          'text' => 'Level 1.2.1'
                          'child' => array(
                              // etc.
                         ),
                      array(
                          'text' => 'Level 1.2.2'
                          'child' => array(
                              // etc.
                         ),
                      )
                   )
              )
          )
      );
      

      Usage:

      $nav = makeArray($links);
      makeList($nav);
      


      I've spent many spare hours trying to work this out, and the original code which I have given here is still the best solution I've been able to produce.

      How can I make this happen without that awful function (which is limited to a depth of 3), and have an infinite number of levels? Is there a more elegant solution to this?

      解决方案

      Print:

      function printListRecursive(&$list,$parent=0){
          $foundSome = false;
          for( $i=0,$c=count($list);$i<$c;$i++ ){
              if( $list[$i]['parent_id']==$parent ){
                  if( $foundSome==false ){
                      echo '<ul>';
                      $foundSome = true;
                  }
                  echo '<li>'.$list[$i]['text'].'</li>';
                  printListRecursive($list,$list[$i]['id']);
              }
          }
          if( $foundSome ){
              echo '</ul>';
          }
      }
      
      printListRecursive($list);
      

      Create multidimensional array:

      function makeListRecursive(&$list,$parent=0){
          $result = array();
          for( $i=0,$c=count($list);$i<$c;$i++ ){
              if( $list[$i]['parent_id']==$parent ){
                  $list[$i]['childs'] = makeListRecursive($list,$list[$i]['id']);
                  $result[] = $list[$i];
              }
          }
          return $result;
      }
      
      $result = array();
      $result = makeListRecursive($list);
      echo '<pre>';
      var_dump($result);
      echo '</pre>';
      

      这篇关于如何从平面数组构建具有无限深度的嵌套 HTML 列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆