2010-11-30 24 views
6

Tengo una matriz multidimensional anidada a una profundidad desconocida/ilimitada. Me gustaría poder recorrer todos los elementos. No quiero usar, foreach(){foreach(){foreach(){}}} ya que no sé la profundidad.Matrices multidimensionales anidadas a profundidad ilimitada

Finalmente estoy buscando todas las matrices anidadas llamadas "xyz". ¿Alguien tiene alguna sugerencia?

Respuesta

1

El uso de los comentarios anteriores, he encontrado la respuesta:

function findXyz($array){ 
    foreach($array as $foo=>$bar){ 
     if (is_array($bar)){ 
     if ($bar["xyz"]){ 
      echo "<br />The array of xyz has now been found"; 
      print_r($bar['xyz']); 
     }else{ 
      findXyz($bar); 
     } 
     } 
    } 
} 
findXyz($myarray); 

Este bucle a través de todas las matrices anidadas y busca cualquier elemento que tiene un sub-conjunto de XYZ, según mi original solicitud. array_walk_array y RecursiveIteratorIterator no pudieron lograr esto.

3

Recursividad.

Escribe una función que recorre una matriz; para cada elemento que también es una matriz, se llama a sí mismo; de lo contrario, cuando encuentra la cadena objetivo, regresa.

+0

esta función recursiva deberá usar para o foreach – Thariama

+0

Sí, pero solo una vez. No con un nivel de anidación codificado. – tdammers

0

¿Has pensado en utilizar array_walk_recursive para esto?

Otro enfoque (más lento) sería flatten the array primero antes de realizar una búsqueda, es decir:

$myarray = array('a','b',array(array(array('x'),'y','z')),array(array('p'))); 

function array_flatten($array,$return) 
{ 
    for($x = 0; $x <= count($array); $x++) 
    { 
     if(is_array($array[$x])) 
     { 
      $return = array_flatten($array[$x],$return); 
     } 
     else 
     { 
      if($array[$x]) 
      { 
       $return[] = $array[$x]; 
      } 
     } 
    } 
    return $return; 
} 

$res = array_flatten($myarray,array()); 

O, para una búsqueda recursiva, ver here para ver un ejemplo:

function arrayRecursiveSearch($needle, $haystack, $path=""){ 
    if(!is_array($haystack)){ 
    die("second argument is not array"); 
    } 

    global $matches; 

    foreach($haystack as $key=>$value) 
    { 
    if(preg_match("/$needle/i", $key)){ 
     $matches[] = array($path . "$key/", "KEY: $key"); 
    } 

    if(is_array($value)){ 
     $path .= "$key/"; 
     arrayRecursiveSearch($needle, $value, $path); 
     unset($path); 
    }else{ 
     if(preg_match("/$needle/i", $value)){ 
     $matches[] = array($path . "$key/", "VALUE: $value"); 
     } 
    } 
    } 

    return $matches; 
} 

$arr = array("Asia"=>array('rambutan','duku'), 
       "Australia"=>array('pear','kiwi'), 
       "Arab"=>array('kurma')); 

print_r(arrayRecursiveSearch("ra",$arr)); 
+0

array_walk_recursive funcionaría maravillosamente, a excepción de esta pequeña cláusula en la documentación en PHP.net: "Puede observar que la clave 'dulce' nunca se muestra.Cualquier clave que contenga una matriz no se pasará a la función. " – stevenmc

3

Hay una vasta diferencia entre desconocido e ilimitado. Sin embargo, puede utilizar el SPL Iterators en lugar de utilizar múltiples bucles anidados foreach.

Ejemplo:

$array_obj = new RecursiveIteratorIterator(new RecursiveArrayIterator($array)); 
foreach($array_obj as $key => $value) { 
    echo $value; 
} 
+0

Esto sufre el mismo problema que array_walk_array, en el sentido de que si una matriz contiene otra matriz, el índice no se pasará :( – stevenmc

1

Tome un vistazo a la interfaz RecursiveIteratorIterator.

$interface = new RecursiveIteratorIterator(new RecursiveArrayIterator($your_array)); 
foreach($interface as $k=>$v) { /* your function*/ } 
10

Finalmente estoy buscando todas las matrices anidadas llamadas "xyz". ¿Alguien tiene alguna sugerencia?

Sure. Sobre la base de las sugerencias para utilizar algunos iteradores, que puede hacer:

$iterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($array), 
    RecursiveIteratorIterator::SELF_FIRST 
); 
foreach ($iterator as $key => $item) { 
    if (is_array($item) && $key === 'xyz') { 
     echo "Found xyz: "; 
     var_dump($item); 
    } 
} 

La diferencia importante entre las otras respuestas y esto es que la bandera RecursiveIteratorIterator::SELF_FIRST está siendo empleada para hacer la no hoja (es decir los padres) artículos (es decir, arrays) visibles al iterar.

También podría hacer uso de un ParentIterator alrededor del iterador del array, en lugar de verificar las matrices dentro del ciclo, para hacer que el último sea un poco más ordenado.

Cuestiones relacionadas