2009-07-25 8 views
2

Supposons que j'ai un tableau en PHP qui ressemble à cecinœuds feuilles Extrait du tableau multidimensionnel en PHP

array 
(
    array(0) 
    (
     array(0) 
     (
     . 
     . 
     . 
     ) 

     . 
     . 
     array(10) 
     (
     .. 
     ) 
    ) 

    . 
    . 
    . 
    array(n) 
    (

    array(0) 
    (
    ) 
    ) 
) 

Et je besoin de tous les éléments de la feuille de ce tableau mulit dimensions dans un réseau linéaire, comment devrais-je faire cela sans recourir à la récursivité, comme ça?

function getChild($element) 
{ 

    foreach($element as $e) 
    { 

     if (is_array($e) 
     { 
      getChild($e); 
     } 
    } 
} 

Note: extrait de code ci-dessus, horriblement inachevé

Mise à jour: exemple de tableau

Array 
(
    [0] => Array 
     (
      [0] => Array 
       (
        [0] => Seller Object 
         (
          [credits:private] => 5000000 
          [balance:private] => 4998970 
          [queueid:private] => 0 
          [sellerid:private] => 2 
          [dateTime:private] => 2009-07-25 17:53:10 
         ) 

       ) 

     ) 

... snipped.

[2] => Array 
    (
     [0] => Array 
      (
       [0] => Seller Object 
        (
         [credits:private] => 10000000 
         [balance:private] => 9997940 
         [queueid:private] => 135 
         [sellerid:private] => 234 
         [dateTime:private] => 2009-07-14 23:36:00 
        ) 

      ) 

    ....snipped.... 

    ) 

)

+0

Y at-il une raison que vous ne voulez pas utiliser la récursivité? On dirait la technique la plus appropriée. – deceze

+0

Qu'est-ce qui est horriblement incomplet à propos de cet extrait? – SilentGhost

+0

J'ai omis le tableau final pour rassembler les éléments, et laissé de côté la partie else de l'instruction if; Quant à savoir pourquoi aucune récursion, c'est juste une préférence personnelle, et une peur que le script ne se transforme en boucle infinie. – Extrakun

Répondre

10

En fait, il y a une seule fonction qui fera l'affaire, consultez la page de manuel à l'adresse: http://php.net/manual/en/function.array-walk-recursive.php

extrait rapide adapté de la page:

$data = array('test' => array('deeper' => array('last' => 'foo'), 'bar'), 'baz'); 

var_dump($data); 

function printValue($value, $key, $userData) 
{ 
    //echo "$value\n"; 
    $userData[] = $value; 
} 


$result = new ArrayObject(); 
array_walk_recursive($data, 'printValue', $result); 

var_dump($result); 
2

Essayez ceci:

function getLeafs($element) { 
    $leafs = array(); 
    foreach ($element as $e) { 
     if (is_array($e)) { 
      $leafs = array_merge($leafs, getLeafs($e)); 
     } else { 
      $leafs[] = $e; 
     } 
    } 
    return $leafs; 
} 

Modifier Apparemment, vous ne voulez pas une solution récursive. Voici donc une solution itérative qui utilise une pile:

function getLeafs($element) { 
    $stack = array($element); 
    $leafs = array(); 
    while ($item = array_pop($stack)) { 
     while ($e = array_shift($item)) { 
      if (is_array($e)) { 
       array_push($stack, array($item)); 
       array_push($stack, $e); 
       break; 
      } else { 
       $leafs[] = $e; 
      } 
     } 
    } 
    return $leafs; 
} 
1

Il n'y a pas de fonction d'aplatissement pour obtenir directement les feuilles. Vous devez utiliser récursion pour vérifier chaque tableau si a plus d'enfants de tableau et seulement quand vous arrivez au fond pour déplacer l'élément à un tableau plat de résultat.

6

Vous pouvez utiliser itérateurs, par exemple:

$result = array(); 
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::LEAVES_ONLY) as $value) { 
    $result[] = $value; 
} 
+0

+1, utilisez plus de spl, http://php.net/spl – VolkerK

+0

Est-il acceptable de confirmer avec vous si cela fonctionne? Je l'ai essayé mais la boucle ne s'exécute jamais – Extrakun

+0

Je l'ai testé avec un simple tableau, et cela fonctionne, vous pourriez peut-être poster un exemple du tableau que vous utilisez. J'ai essayé '$ array = array ( \t tableau ('a', tableau ('b', 'c', 'd', tableau ('f'))), \t 'c' \t);' –

2

Utilisez une pile:

<?php 

$data = array(array(array("foo"),"bar"),"baz"); 

$results = array(); 
$process = $data; 
while (count($process) > 0) { 
    $current = array_pop($process); 
    if (is_array($current)) { 
     // Using a loop for clarity. You could use array_merge() here. 
     foreach ($current as $item) { 
      // As an optimization you could add "flat" items directly to the results array here. 
      array_push($process, $item); 
     } 
    } else { 
     array_push($results, $current); 
    } 
} 

print_r($results); 

Sortie:

Array 
(
    [0] => baz 
    [1] => bar 
    [2] => foo 
) 

Cela devrait être plus efficace de la mémoire que l'approche récursive. Malgré le fait que nous effectuons beaucoup de manipulation de tableaux ici, PHP a une sémantique de copy-on-write pour que les zvals réels des données réelles ne soient pas dupliqués en mémoire.

1

Nous venons de la même question et a utilisé un autre méthode qui n'a pas été mentionnée. La réponse acceptée nécessite que le ArrayObject class fonctionne correctement. Il peut être fait avec la array primitive et le mot-clé use dans le anonymous function (PHP> = 5.3):

<?php 
$data = array(
    array(1,2,3,4,5), 
    array(6,7,8,9,0), 
); 
$result = array(); 
array_walk_recursive($data, function($v) use (&$result) { # by reference 
    $result[] = $v; 
}); 
var_dump($result); 
Questions connexes