2010-10-20 23 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"; 
} 

Ehi, questo metodo cerca una chiave specifica in una matrice associativa e restituisce il valore associato. C'è qualche problema con la ricorsione. Qualche indizio?Cerca una chiave in una serie, in modo ricorsivo

+0

Come mai non si sa a che livello è? –

risposta

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

questo funzionerà!

è necessario interrompere la ricerca profonda ricorsiva, restituendo falso e quindi verificarlo nella funzione.

è possibile trovare ulteriori esempi di funzioni (come l'utilizzo di RecursiveArrayIterator e più) in questo link: http://php.net/manual/en/function.array-search.php

+0

non riesce se il valore della chiave è '0'/zero. utilizzare quindi un muggito: fn 'recursiveFind'. – phpJs

31

Forse è eccessivo, ma è divertente da usare RecursiveIterators :)

UPDATE: Forse era eccessivo con le vecchie versioni di PHP, ma con> = 5.6 (specialmente con 7.0) lo userei senza dubbio.

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

UPDATE: Inoltre, dal PHP 5.6, con generatori si può facilmente iterare su tutti gli elementi che corrispondono al filtro, non solo la prima:

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

Grazie. Questo mi ha salvato. Ricordati di cambiare '===' a '==' se non hai bisogno di fare un rigoroso confronto della chiave. – Batandwa

+0

Attenzione, se la chiave appare più volte nella ricorsione, questo ottiene solo il valore del primo.Per modificarli tutti in questo modo: 'function recursiveFind (array $ array, $ needle) { $ iterator = new RecursiveArrayIterator ($ array); $ recursive = new RecursiveIteratorIterator ( $ iterator, RecursiveIteratorIterator :: SELF_FIRST ); $ return = []; foreach ($ ricorsivo come $ chiave => valore $) { if ($ chiave === $ ago) { $ ritorno [] = $ valore; } } return $ return; } ' –

+0

Dopo PHP 5.6 userei un generatore per questo, chiamando' yield' invece di 'return'. – xPheRe

1

prova:

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

La risposta fornita da xPheRe è stata estremamente utile, ma non ha risolto il problema nella mia implementazione. Nella nostra struttura dati ci sono più array associativi nidificati e possono esserci più occorrenze di una determinata chiave.

Per soddisfare i nostri scopi, avevo bisogno di implementare un array di supporto che è stato aggiornato mentre si attraversava l'intera struttura, invece di tornare alla prima partita. Il vero lavoro è stato fornito da un altro poster, ma volevo dire grazie e condividere il passaggio finale che dovevo coprire.

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

Funziona alla grande per le mie esigenze! –

0

La soluzione migliore sopra non trova la caso se la chiave viene ripetuta e restituisce solo il primo valore, qui ho tutti i valori in un array invece:

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; 
} 
Problemi correlati