2010-08-26 13 views
8

Quiero saber el nivel de una matriz mientras se está construyendo.¿Es posible contar el número de dimensiones en una matriz?

El código recorre un grupo de directorios para crear una gran matriz multidimensional.

Como se está creando la matriz, quiero saber qué tan profundo en la matriz que soy.

1 2 3 4 
--------------------- 
Root 
    A 
      A2 
      A3 
      A4 
       A4a 
    B 
      B2 
      B3 
    C 
    D 
    E 
      E2 
       E2a 
      E3 

En el ejemplo anterior, el directorio raíz está en el nivel 1. Todas las letras mayúsculas individuales están en el nivel 2. Todas las letras mayúsculas con un número están en el nivel 3. Todas las letras mayúsculas con un número y una letra minúscula están en el nivel 4.

Como estoy construyendo la matriz, ¿hay alguna manera de saber en qué nivel estoy? La matriz se está creando con una función recursiva.

Esta es una pregunta de PHP.

+2

No, no hay forma, ¿por qué no pasa la profundidad actual a su función recursiva? –

+0

¿Se puede publicar la función recursiva? – sjobe

+0

Lo siento, no puedo publicar la función recursiva. Gracias por todos los comentarios y respuestas! –

Respuesta

3

Una respuesta rápida y fácil es simplemente agregar un parámetro de "profundidad" a su función e incrementarla cuando la función se llame a sí misma.

+1

+1 Uso de recursión para trabajar con el producto de recursión - Me gusta el sonido de ese. – BoltClock

+0

-1 No entiendo cómo esto cuenta la dimensión. En mi opinión, solo cubre el caso cuando la subdimensión está en el primer elemento de la matriz. – NikiC

+0

@nikic Disculpas: me olvidé de un [0] en el código ... – Basic

3

Esto debería hacer:

function array_depth($array) { 
    $max_depth = 1; 

    foreach ($array as $value) { 
     if (is_array($value)) { 
      $depth = array_depth($value) + 1; 

      if ($depth > $max_depth) { 
       $max_depth = $depth; 
      } 
     } 
    } 

    return $max_depth; 
} 
0
function calc_dimensions(array $array) { 
    $dimensions = 1; 
    $max = 0; 
    foreach ($array as $value) { 
     if (is_array($value)) { 
      $subDimensions = calc_dimensions($value); 
      if ($subDimensions > $max) { 
       $max = $subDimensions; 
      } 
     } 
    } 

    return $dimensions+$max; 
} 

$array = array(
    array(
     array(
      4 => 5, 
      array(
       6 => 6 
      ) 
     ) 
    ), 
    1 => 5 
); 

echo calc_dimensions($array)."\n"; 
+0

¿Por qué usa tanto '$ max' como' $ dimensions'. Uno de ellos sería suficiente. – NikiC

+0

sí, por supuesto :) – bobrik

0

Quizás esté haciendo la pregunta equivocada. ¿Cuál es el objetivo final? Por ejemplo, hay una clase RecursiveDirectoryIterator dentro de SPL, ¿quizás eso sea suficiente para usted? Construir una gran matriz multidimensional comerá mucha memoria, ¿entonces quizás bastaría con repetir iterativamente todos esos archivos recursivamente?

+0

Gracias por el comentario. La estructura del directorio y los contenidos rara vez cambian, y cuando lo hace, emitimos una nueva versión. Así que estoy almacenando en caché la matriz después de que se creó. De lo contrario, sí, estaríamos jodidos. –

5

Esto podría ser tangencial a su pregunta sobre la matriz, pero podría matar dos pájaros de un tiro utilizando un iterador de directorio recursivo.

$path_to_root = __DIR__; 
$directories = new ParentIterator(new RecursiveDirectoryIterator($path_to_root, RecursiveDirectoryIterator::CURRENT_AS_SELF)); 
$iterator  = new RecursiveIteratorIterator($directories, RecursiveIteratorIterator::SELF_FIRST); 

foreach ($iterator as $item) 
{ 
    printf("%d %s\n", $iterator->getDepth() + 1, $item->getSubPathname()); 
} 

que sería algo como de salida:

1 Root 
2 Root/A 
3 Root/A/A2 
3 Root/A/A3 
3 Root/A/A4 
4 Root/A/A4/A4a 
2 Root/B 
3 Root/B/B2 
3 Root/B/B3 
2 Root/C 
2 Root/D 
2 Root/E 
3 Root/E/E2 
4 Root/E/E2/E2a 
3 Root/E/E3 

Como se puede ver RecursiveIteratorIterator::getDepth() se utiliza para obtener la profundidad actual del iterador recursivo, que es la razón por sugerir este enfoque.


alternativa (si tiene que utilizar una matriz)

Asumiendo que su estructura de matriz se ve algo como:

$dirs = array(
    'Root' => array(
     'A' => array(
      'A2' => array(), 
      'A3' => array(), 
      'A4' => array(
       'A4a' => array(), 
      ), 
     ), 
     'B' => array(
      'B2' => array(), 
      'B3' => array(), 
     ), 
     'C' => array(), 
     'D' => array(), 
     'E' => array(
      'E2' => array(
       'E2a' => array(), 
      ), 
      'E3' => array(), 
     ), 
    ), 
); 

A continuación, una muy similar enfoque para obtener los valores de un directorio recursivo iterador (pero esta vez con un iterador de matriz recursivo) puede ser utilizado. Un bucle rápido sobre las matrices "principales" puede darnos la "ruta" desde el elemento actual hasta la raíz.

$recursive = new ParentIterator(new RecursiveArrayiterator($dirs)); 
$iterator = new RecursiveIteratorIterator($recursive, RecursiveIteratorIterator::SELF_FIRST); 

foreach ($iterator as $item) 
{ 
    // Build path from "parent" array keys 
    for ($path = "", $i = 0; $i <= $iterator->getDepth(); $i++) { 
     $path .= "/" . $iterator->getSubIterator($i)->key(); 
    } 
    // Output depth and "path" 
    printf("%d %s\n", $iterator->getDepth() + 1, ltrim($path, "/")); 
} 

La salida sería la misma que la anterior para el iterador del directorio.

TL; DR Podemos usar iteradores recursivos del SPL iterators para hacer que el trabajo con estructuras recursivas/profundas sea mucho más simple.

TL; DR; TL; DR SPL, diablos, sí!

Cuestiones relacionadas