2010-10-20 15 views
16
private function find($needle, $haystack) { 
    foreach ($haystack as $name => $file) { 
     if ($needle == $name) { 
      return $file; 
     } else if(is_array($file)) { //is folder 
      return $this->find($needle, $file); //file is the new haystack 
     }    
    } 

    return "did not find"; 
} 

Oye, este método busca una clave específica en una matriz asociativa y devuelve el valor asociado a ella. Hay un problema con la recursión. ¿Cualquier pista?Buscar una clave en una matriz, recursivamente

+0

¿Cómo es que no sabe ¿En qué nivel está? –

Respuesta

12
function array_search_key($needle_key, $array) { 
    foreach($array AS $key=>$value){ 
    if($key == $needle_key) return $value; 
    if(is_array($value)){ 
     if(($result = array_search_key($needle_key,$value)) !== false) 
     return $result; 
    } 
    } 
    return false; 
} 

esto funcionará!

tiene que dejar la profunda búsqueda recursiva, por una falsa retirada y después comprobar que en la función.

se pueden encontrar más ejemplos de funciones (como el uso de RecursiveArrayIterator y más) en este enlace: http://php.net/manual/en/function.array-search.php

+0

falla si el valor clave es '0'/cero. use un fuelle luego: fn 'recursive Find'. – phpJs

31

Tal vez sea una exageración, pero es divertido de usar RecursiveIterators :)

ACTUALIZACIÓN: Tal vez fue excesivo con versiones antiguas de PHP, pero con> = 5.6 (especialmente con 7.0) lo usaría totalmente sin dudarlo.

function recursiveFind(array $haystack, $needle) 
{ 
    $iterator = new RecursiveArrayIterator($haystack); 
    $recursive = new RecursiveIteratorIterator(
     $iterator, 
     RecursiveIteratorIterator::SELF_FIRST 
    ); 
    foreach ($recursive as $key => $value) { 
     if ($key === $needle) { 
      return $value; 
     } 
    } 
} 

ACTUALIZACIÓN: También, a partir de PHP 5.6, con los generadores se puede recorrer fácilmente a través de todos los elementos que pasan el filtro, no sólo la primera de ellas:

function recursiveFind(array $haystack, $needle) 
{ 
    $iterator = new RecursiveArrayIterator($haystack); 
    $recursive = new RecursiveIteratorIterator(
     $iterator, 
     RecursiveIteratorIterator::SELF_FIRST 
    ); 
    foreach ($recursive as $key => $value) { 
     if ($key === $needle) { 
      yield $value; 
     } 
    } 
} 

// Usage 
foreach (recursiveFind($haystack, $needle) as $value) { 
    // Use `$value` here 
} 
+4

Gracias. Esto me salvó. Recuerde cambiar '===' a '==' si no necesita hacer una comparación estricta de la clave. – Batandwa

+0

Cuidado, si la clave aparece varias veces en la recursión, solo obtiene el valor de la primera.Para obtenerlos todos, modifíquelo así: 'function recursive Find (array $ array, $ needle) { $ iterator = new RecursiveArrayIterator ($ array); $ recursive = new RecursiveIteratorIterator ( $ iterator, RecursiveIteratorIterator :: SELF_FIRST ); $ return = []; foreach ($ recursivo como $ clave => $ valor) { if ($ clave === $ aguja) { $ return [] = $ value; } } return $ return; } ' –

+0

Después de PHP 5.6 usaría un generador para esto, llamando' yield' en lugar de 'return'. – xPheRe

1

probar esto:

array_walk_recursive(
    $arrayToFindKey, 
    function($value, $key, $matchingKey){ 
     return (strcasecmp($key, $matchingKey) == 0)? true : false; 
    } 
    , 'matchingKeyValue' 
); 
4

la respuesta proporcionada por Xphere fue de gran ayuda, pero no acababa de resolver el problema en mi aplicación. Existen múltiples matrices asociativas anidadas en nuestra estructura de datos, y puede haber múltiples ocurrencias de cualquier clave dada.

Con el fin de satisfacer a nuestros propósitos, que necesitaba para poner en práctica un conjunto de soportes que se actualiza al atravesar toda la estructura, en vez de volver en el primer partido. El trabajo real fue proporcionado por otro afiche, pero quería dar las gracias y compartir el último paso que tuve que cubrir.

public function recursiveFind(array $array, $needle) 
{ 
    $iterator = new RecursiveArrayIterator($array); 
    $recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST); 
    $aHitList = array(); 
    foreach ($recursive as $key => $value) { 
     if ($key === $needle) { 
      array_push($aHitList, $value); 
     } 
    } 
    return $aHitList; 
} 
+0

¡Funciona muy bien para mis necesidades! –

0

La mejor solución anterior no encuentra el caso si se repite la llave y sólo devuelve el primer valor, aquí me sale todos los valores en una matriz en su lugar:

function recursiveFind(array $array, $needle) { 
    $iterator = new RecursiveArrayIterator($array); 
    $recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST); 
    $return = []; 
    foreach ($recursive as $key => $value) { 
    if ($key === $needle) { 
     $return[] = $value; 
    } 
    } 
    return $return; 
} 
Cuestiones relacionadas