2011-09-28 5 views
9

Qualcuno può aiutarmi con un po 'di codice o istruzioni su come camminare in modo ricorsivo su un array e quando si raggiunge l'ultimo elemento stampare il percorso completo ad esso? Un semplice eco funzionerà perché adatterò il codice ad un'altra funzione che sto sviluppando.Cammina l'array in modo ricorsivo e stampa il percorso del cammino

La funzione non deve calcolare la dimensione di matrice perché questo parametro sarà passata:

Esempio:

$depth = 8; 

$array[1][3][5][6][9][5][8][9]; 

Quando la funzione reachs l'elemento 8 è stampare tutto il relativo percorso:

//print path 
'1 -> 3 -> 5 -> 6 -> 9 -> 5 -> 8 -> 9' 
  • Come ho detto, solo la stampa in questo formato funzionerà causa lo farò implementare il codice in qualche altra funzione.

  • le chiavi di matrice possono avere lo stesso valore. Ovviamente non lo stesso valore nella stessa sequenza per l'intero arary.

Aggiornato:

Passeggiata in modo ricorsivo Funzione:

$someArray[1][2][3] = 'end'; 
$someArray[1][2][6] = 'end'; 
$someArray[1][3][6] = 'end'; 
$someArray[4][3][7] = 'end'; 

function listArrayRecursive(&$array_name, $ident = 0){ 
    if (is_array($array_name)){ 
     foreach ($array_name as $k => &$v){ 
      if (is_array($v)){ 
       for ($i=0; $i < $ident * 10; $i++){ echo "&nbsp;"; } 
       echo $k . " : " . "<br>"; 
       listArrayRecursive($v, $ident + 1); 
      }else{ 
       for ($i=0; $i < $ident * 10; $i++){ echo "&nbsp;"; } 
       echo $k . " : " . $v . "<br>"; 
      } 
     } 
    }else{ 
     echo "Variable = " . $array_name; 
    } 
} 

listArrayRecursive($someArray); 

stamperà:

1 : 
     2 : 
       3 : end 
       6 : end 
     3 : 
       6 : end 
4 : 
     3 : 
       7 : end 

Ora, come posso anche stampare il percorso della matrice ogni volta che raggiunge la fine? Per esempio:

1 : 
     2 : 
       3 : end : path -> 1,2,3 
       6 : end : path -> 1,2,6 
     3 : 
       6 : end : path -> 1,3,6 
4 : 
     3 : 
       7 : end : path -> 4,3,7 

codice modificato AGGIUNTA DI UN PARAM TERZO per registrare il percorso:

$someArray[1][2][3] = 'end'; 
$someArray[1][2][6] = 'end'; 
$someArray[1][3][6] = 'end'; 
$someArray[4][3][7] = 'end'; 
$someArray[3][2] = 'end'; 

function listArrayRecursive(&$array_name, $ident = 0, $path = null){ 
    foreach ($array_name as $k => &$v){ 
     if (is_array($v)){ 
      for ($i=0; $i < $ident * 10; $i++){ echo "&nbsp;"; } 
      echo $k . " : " . "<br>"; 
      $path .= $k . ', '; 
      listArrayRecursive($v, $ident + 1, $path); 
     }else{ 
      for ($i=0; $i < $ident * 10; $i++){ echo "&nbsp;"; } 
      echo $k . " : " . $v . ' - path -> ' . $path . "<br>"; 
     } 
    } 
} 

listArrayRecursive($someArray); 

stamperà:

1 : 
      2 : 
        3 : end - path -> 1, 2, 
        6 : end - path -> 1, 2, 
      3 : 
        6 : end - path -> 1, 2, 3, 
4 : 
      3 : 
        7 : end - path -> 1, 4, 3, 
3 : 
      2 : end - path -> 1, 4, 3, 
+0

Bene, è compito fondamentale di risolvere con la ricorsione. Che cosa hai provato? – zerkms

+0

@zerkms in realtà ho questo codice per la ricorsione http://codepad.org/iyrcdfQP ma sono bloccato sulla parte per tracciare il percorso della chiave $ corrente. – Henrique

+0

Puoi dare un esempio più chiaro, che dire di più elementi all'interno di una determinata profondità di array o se l'array non è nidificato come "$ profondità"? Che problema è questo risolvere? – salathe

risposta

14

È possibile utilizzare uno RecursiveIteratorIterator (docs) per sottrarsi alla ricorsione attraverso gli array.

function listArrayRecursive($someArray) { 
    $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($someArray), RecursiveIteratorIterator::SELF_FIRST); 
    foreach ($iterator as $k => $v) { 
     $indent = str_repeat('&nbsp;', 10 * $iterator->getDepth()); 
     // Not at end: show key only 
     if ($iterator->hasChildren()) { 
      echo "$indent$k :<br>"; 
     // At end: show key, value and path 
     } else { 
      for ($p = array(), $i = 0, $z = $iterator->getDepth(); $i <= $z; $i++) { 
       $p[] = $iterator->getSubIterator($i)->key(); 
      } 
      $path = implode(',', $p); 
      echo "$indent$k : $v : path -> $path<br>"; 
     } 
    } 
} 
+0

Questo suona molto meglio! Grazie mille!!! – Henrique

+0

questo è fantastico! grazie! – claudioivp

+0

Cerchi esattamente questo, grazie. –

0

Questo esempio è quello di dare un'idea, non per risolvere il compito reale.

function recursiveSearch($array,$search){ 
    foreach($array as $key=>$val){ 
     if($val==$search)return $key; 
     $x=recursiveSearch($array[$key],$search); 
     if($x)return $key.' -> '.$x; 
    } 
} 

echo recursiveSearch($array,'search'); 

Se non viene trovata alcuna corrispondenza, viene restituito null.

0
$a= array(1,2,3,4,5,6); 
$val = end($a); 
print_array($a,$val); 
function print_array(&$arr, $val) 
{ 
    if ($val === false) 
     return; 

    $curr = prev($arr); 
    print_array($arr,$curr); 
    echo $val; 
} 
-1

È possibile aggiungere un terzo parametro che contiene il percorso effettivo come Stringa. Alla fine puoi stamparlo poi.

+0

già provato ma non così semplice. Controlla il codice che ho appena modificato. Qualche consiglio? – Henrique

0

Ho appena scritto una funzione che rende ricorsiva loop un po 'più facile: Simile a array_walk_recursive ma con qualche funzionalità extra

public static function walk($array, $callback, $custom = null, $recursive = false, $info = []) 
{ 
    $r = $recursive; 
    if (gettype($r) === 'integer') { 
     $r--; 
    } 
    $info['depth'] = empty($info)?1:$info['depth'] + 1; 
    $info['count'] = count($array); 
    $info['i'] = 1; 
    foreach($array as $k => $v) { 
     if (is_array($v) && $r > 0) { 
      $array[$k] = static::walk($v, $callback, $custom, $r, $info); 
     } else { 
      $array[$k] = $callback($v, $k, $custom, $info); 
     } 
     $info['i'] ++; 
    } 
    return $array; 
} 

public static function walkable($v, $k, $custom, $info) 
{ 
    if (is_string($v)) { 
     return $v." [ custom: {$custom['key']} ] [ level: ".$info['depth'].' | No '.$info['i'].' of '.$info['count']." ]"; 
    } 
    return $v; 
} 

Chiamato in questo modo:

$result = Namespace\ClassName::walk($array, ['Namespace\ClassName', 'walkable'], ['key'=>'value'], true); 

Impostazione ricorsivo per false valuterà solo il primo livello.

L'impostazione ricorsiva su true lo farà attraversare l'intero array.

L'impostazione ricorsiva su un numero intero comporterà il passaggio solo a tale profondità.

Le funzioni percorribili possono essere referenziate o passate alla richiamata come funzione anonima.

(prevede: valore, chiave, personalizzato, informazioni) Il valore restituito sostituisce il valore corrente.

I dati personalizzati possono essere passati e vengono fornite alcune informazioni aggiuntive.

È possibile espandere la funzione Walk se sono necessarie ulteriori informazioni.

0

Ho avuto un problema simile. Ecco una soluzione First-Search-ish (senza profondità del percorso inclusa, raggiunge fino alla fine dell'array). Commenta la 'se' dichiarazione se u non si vuole includere il valore:

$output = array(); 
retrievePath($someArray, $output); 

function retrievePath($someArray, array &$pathKeeper) 
{ 
    if(!is_array($someArray)){ // $someArray == "end" 
     $element = array_pop($pathKeeper) ?? '';// if the array is empty pop returns null, we don't want that 
     array_push($pathKeeper, $element . '->'. $someArray); 
    } else{ 
     end($someArray);//we want to get the last element from the array so we move the internal pointer to it's end 
     $endElKey = key($someArray);//take the key where the pointer is 
     reset($someArray); 
     foreach($someArray as $key=>$value){ 
      $element = array_pop($pathKeeper); 
      array_push($pathKeeper, $element === null ? $key : $element . '->' . $key);// we don't want '->' at the beginning 
      retrievePath($value, $pathKeeper); 
      if($key != $endElKey) //we check whether this is not the last loop 
       array_push($pathKeeper, $element); 
     } 
    } 
} 
0
<?php 
function printListRecursive($a, $var='', $i = 0) { 
    if (!is_array($a)) { 
     $var .= $a; 
     return $var; 
    } 
    $string = ""; 
    foreach ($a as $k => $value) { 
     $string .= str_repeat("&nbsp;&nbsp;", $i) .' - '. $k . ':'; 
     if (!is_array($value)) { 
      $string .= $value . '<br />'; 
     } else { 
      $string .= '<br />'; 
      $string .= printListRecursive($value, $var, $i + 1); 
     } 
    } 
    return $string; 
} 
$test_array = [ 
    'America' => [ 
     'Argentina' => 'Buenos Aires', 
     'Peru' => 'Lima' 
    ], 
    'Europe' => [ 
     'Ireland' => 'Dublin', 
     'France' => 'Paris', 
     'Italy' => 'Rome' 
    ] 
]; 
$result = printListRecursive($test_array); 
echo $result; 
?> 

Check code here

Problemi correlati