Pour aplatir sans récursion (comme vous l'avez demandé), vous pouvez utiliser une pile. Naturellement, vous pouvez mettre cela dans une fonction à part comme array_flatten
. Voici une version qui fonctionne sans clés :
function array_flatten(array $array)
{
$flat = array(); // initialiser le tableau de retour
$stack = array_values($array); // initialiser la pile
while($stack) // traiter la pile jusqu'à la fin
{
$value = array_shift($stack);
if (is_array($value)) // une valeur à traiter davantage
{
array_unshift($stack, ...$value);
}
else // une valeur à prendre
{
$flat[] = $value;
}
}
return $flat;
}
Les éléments sont traités dans leur ordre. Comme les sous-éléments seront déplacés en haut de la pile, ils seront traités ensuite.
Il est possible de prendre en compte les clés également, cependant, vous aurez besoin d'une stratégie différente pour gérer la pile. Cela est nécessaire car vous devez traiter les clés en double possibles dans les sous-tableaux. Une réponse similaire dans une question connexe : PHP Parcourir un tableau multidimensionnel tout en préservant les clés
Je ne suis pas spécifiquement sûr, mais je l'avais testé dans le passé : Le RecurisiveIterator
utilise la récursion, donc cela dépend de ce dont vous avez vraiment besoin. Il devrait être possible de créer un itérateur récursif basé sur des piles également :
foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
{
echo "** ($key) $value\n";
}
Démo
Je n'ai pas encore eu le temps d'implémenter la pile basée sur RecursiveIterator
ce qui je pense est une bonne idée.
17 votes
Pourquoi éviter la récursivité?
5 votes
Dupe (mostly) stackoverflow.com/questions/526556/…
4 votes
Vous ne pouvez rien faire avec tous les éléments d'arrays d'une profondeur arbitraire sans récursion (vous pouvez le déguiser en itération, mais pomme de terre, potahto.) Si vous voulez simplement éviter d'écrire le code de gestion de la récursion vous-même, utilisez dk2.php.net/manual/en/function.array-walk-recursive.php avec un rappel qui ajoute l'élément à un tableau disponible (utilisez global, le paramètre userdata, mettez tout dans une classe et faites référence à $this, etc.)
0 votes
@JorenB: J'aimerais voir une implémentation pouvant être archivée.
0 votes
Jetez un œil à la fonction flatten de Nspl. Vous pouvez également spécifier une profondeur avec elle.
0 votes
Php5.6+ voir la réponse de @joyce-babu, c'est maintenant la meilleure façon de le faire.