2012-10-07 18 views
10

tengo una matriz en PHP, que se ve así:Crear lista anidada de matriz multidimensional

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 
    ) 
) 

Lo que quiero hacer es iterar sobre esta matriz y crear una lista anidada <ol> de ella. Así, el resultado debe ser similar a esto:

<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> 

que he estado tratando de pensar en una manera de cómo podría conseguir este hecho. Pero hasta ahora, todos los intentos han fallado ...

¿Alguien alguna idea de cómo puedo crear una lista anidada <ol> de una matriz como esa?

Tenga en cuenta que no tengo ningún control sobre los datos proporcionados. Simplemente hago una llamada a una API y devuelve datos json, que convierto a una matriz. Y la matriz se ve exactamente como la que describí.

+0

En la superficie parece simple, pero creo que todavía le falta información para obtener la mejor respuesta para su situación. Primero, ¿cómo obtuviste la matriz? ¿Es de una base de datos? ¿Sería posible almacenarlo de manera diferente o estás atrapado de esa manera? ¿La profundidad garantizada no es (ahora o en el futuro) de más de 1 o 2 o alguna vez planearás hacer una cantidad indeterminada de subniveles? ¿Con qué frecuencia se agregarán o eliminarán las categorías? Le sugiero que consulte http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ ya que un modelo anidado puede ser más de lo que necesita. – Mike

Respuesta

13

Debe utilizar recursividad:

En primer lugar la matriz en 'php' sintaxis:

<?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 
    ) 
); 

Aquí el código:

$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); 

?> 

Los resultados:

<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. Título 1 \ n
    1. Título 2 \ n
      1. Título 3 \ n
        1. Título 4 \ n
          1. Título 6 \ n
        2. Título 5 \ n

          editado después de la salida como una solución

          Para evitar hojas vacías:

          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>"); 
          } 
          
          4

          Puede intentar lo siguiente

          $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)); 
          

          salida

          <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> 
          

          función usada

          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

          +1

          excelente respuesta gracias. ¿Puede decirme cómo podemos establecer la profundidad máxima suponiendo que los elementos de la matriz no tienen la tecla 'depth' (ya que no los tengo) ..Necesitamos un '$ level = 0;' y '$ max_level = 3', supongo. ¿Pero cómo colocarlos en tu función? –

          +0

          @Baba, Él hace un buen lugar. Espero que tengas tiempo para revisar esto. –

          1

          La siguiente matriz:

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

          Con esta función:

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

          código PHP:

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

          Devuelve:

          <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> 
          
          Cuestiones relacionadas