Comment aplatir un tableau multidimensionnel?

259

Est-il possible, en PHP, d'aplatir un tableau (bi / multi) dimensionnel sans utiliser de récursivité ou de références?

Je ne m'intéresse qu'aux valeurs pour que les touches puissent être ignorées, je pense dans les lignes de array_map()et array_values().

Alix Axel
la source
17
Pourquoi éviter la récursivité?
JorenB
5
Dupe (principalement) stackoverflow.com/questions/526556/…
cletus
4
Vous ne pouvez rien faire avec tous les éléments d'un tableau arbitrairement profond sans récursivité (vous pouvez le déguiser en itération, mais potato, 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 le tout dans une classe et faites référence à $ this, etc.)
Michael Madsen
@JorenB: J'aimerais qu'une implémentation puisse être archivée.
Alix Axel
Jetez un œil à la fonction d' aplatissement de Nspl . Vous pouvez également spécifier une profondeur avec elle.
Ihor Burlachenko

Réponses:

276

Vous pouvez utiliser la bibliothèque PHP standard (SPL) pour "masquer" la récursivité.

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
foreach($it as $v) {
  echo $v, " ";
}

impressions

1 2 3 4 5 6 7 8 9 
VolkerK
la source
351
Suis-je le seul à penser que «RecursiveIteratorIterator» est un nom idiot?
nilamo
45
C'est plus "logique" que "accrocheur". Tout ne peut pas avoir un nom fantastique comme JOGL, Knol ou Azure :-)
VolkerK
7
Cela ne fonctionnera pas pour les tableaux vides en tant qu'enfants. Ils seront retournés en tant que parent.
2011
45
iterator_to_array($it, false)évite le besoin de foreach.
Alix Axel
3
Sur la base de ce que les autres ont présenté, j'ai pu créer ce petit assistant: function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }j'espère que cela aide les autres.
Mike
296

Depuis PHP 5.3, la solution la plus courte semble être array_walk_recursive()avec la nouvelle syntaxe de fermeture:

function flatten(array $array) {
    $return = array();
    array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
    return $return;
}
trop de php
la source
33
si vous voulez des clés, fonction flatten (array $ array) {$ return = array (); array_walk_recursive ($ array, function ($ a, $ b) use (& $ return) {$ return [$ b] = $ a;}); return $ return; }
Brendon-Van-Heyzen
pouvez-vous réécrire ceci pour l'utiliser avec php 5.2?
Alex
2
@Alex, malheureusement, vous avez besoin de la usesyntaxe pour faire fonctionner cela array_walk_recursivecar il n'acceptera pas le $userdataparamètre facultatif par référence
Tim Seguine
1
On dirait que ça marche bien pour ces tableaux -> ideone.com/DsmApP Mais pas pour ceux-là -> ideone.com/5Kltva Ou est-ce moi?
Sebastian Piskorski
2
@Sebastian Piskorski, c'est parce que vos valeurs sont traitées comme des clés, donc dès que vous introduisez votre propre paire clé => valeur dans un tableau, vos valeurs de tableau dans la première position d'index sont traitées comme des clés sans valeur, et parce que les clés ont pour être unique, où deux clés correspondent, vos valeurs sont ajoutées à la même clé. Une solution simple serait de trier d'abord le tableau. C'est un comportement inhérent à PHP.
Martyn Shutt
92

Solution pour tableau bidimensionnel

Veuillez essayer ceci:

$array  = your array

$result = call_user_func_array('array_merge', $array);

echo "<pre>";
print_r($result);

EDIT: 21 août 13

Voici la solution qui fonctionne pour les tableaux multidimensionnels:

function array_flatten($array) {
    $return = array();
    foreach ($array as $key => $value) {
        if (is_array($value)){
            $return = array_merge($return, array_flatten($value));
        } else {
            $return[$key] = $value;
        }
    }

    return $return;
}

$array  = Your array

$result = array_flatten($array);

echo "<pre>";
print_r($result);

Réf: http://php.net/manual/en/function.call-user-func-array.php

Prasanth Bendra
la source
Merci, le premier a travaillé sur une baie que je recevais de PDO où les autres solutions ne fonctionnaient pas.
JAL
7
C'est une mauvaise stratégie. call_user_func_array('array_merge', [])(remarquez le tableau vide) renvoie null et déclenche une erreur d'avertissement php. C'est une solution astucieuse si vous savez pertinemment que votre tableau ne sera pas vide, mais ce n'est pas une hypothèse commune que beaucoup peuvent faire.
chèvre
Le PO a spécifiquement demandé des solutions non récursives.
Élektra
Wow, cool flattern 2d! Mais pour éviter tout avis, utilisez simplement$result = $array ?call_user_func_array('array_merge', $array) : [];
Alexander Goncharov
cool bruh, mais n'avez-vous pas par hasard un contre-fonction array-deflatten?
FantomX1
65

En PHP 5.6 et supérieur, vous pouvez aplatir les tableaux bidimensionnels array_mergeaprès avoir déballé le tableau extérieur avec l' ...opérateur. Le code est simple et clair.

array_merge(...$a);

Cela fonctionne également avec la collection de tableaux associatifs.

$a = [[10, 20], [30, 40]];
$b = [["x" => "X", "y" => "Y"], ["p" => "P", "q" => "Q"]];

print_r(array_merge(...$a));
print_r(array_merge(...$b));

Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [3] => 40
)
Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

Mais cela ne fonctionne pas lorsque le tableau externe a des clés non numériques. Dans ce cas, vous devrez d' array_valuesabord appeler .

$c = ["a" => ["x" => "X", "y" => "Y"], "b" => ["p" => "P", "q" => "Q"]];
print_r(array_merge(...array_values($c)));

Array
(
    [x] => X
    [y] => Y
    [p] => P
    [q] => Q
)

Mise à jour: basé sur le commentaire de @MohamedGharib

Cela générera une erreur si le tableau externe est vide, car array_mergeserait appelé avec zéro argument. Il peut être évité en ajoutant un tableau vide comme premier argument.

array_merge([], ...$a);
Joyce Babu
la source
1
Cela fonctionne UNIQUEMENT lorsque chaque élément du tableau est un tableau. Si le tableau comprend des types mixtes, tels que des scalaires, une erreur se produit.
Otheus
@Otheus En effet, la solution ci-dessus n'utilise pas la récursivité. Comme vous l'avez dit, cela nécessite un tableau de tableau. Mais du côté positif, cela devrait être beaucoup plus rapide que les autres méthodes, car il n'a pas la surcharge supplémentaire des appels de fonction.
Joyce Babu du
2
Lance une erreur si le tableau externe est vide, pourrait être évitable s'il est combiné avec un tableau videarray_merge([], ...$a);
Mohamed Gharib
@MohamedGharib Belle prise.
Joyce Babu
Si vous utilisez des tableaux associatifs, vous pouvez vérifier cette solution stackoverflow.com/questions/40663687/…
alex
24

Pour aplatir sans récursivité (comme vous l'avez demandé), vous pouvez utiliser une pile . Naturellement, vous pouvez mettre cela dans une fonction qui lui est propre array_flatten. Ce qui suit est une version qui fonctionne sans touches:.

function array_flatten(array $array)
{
    $flat = array(); // initialize return array
    $stack = array_values($array); // initialize stack
    while($stack) // process stack until done
    {
        $value = array_shift($stack);
        if (is_array($value)) // a value to further process
        {
            $stack = array_merge(array_values($value), $stack);
        }
        else // a value to take
        {
           $flat[] = $value;
        }
    }
    return $flat;
}

Les éléments sont traités dans leur ordre. Étant donné que les sous-éléments seront déplacés au-dessus de la pile, ils seront traités ensuite.

Il est également possible de prendre en compte les clés, mais vous aurez besoin d'une stratégie différente pour gérer la pile. Cela est nécessaire car vous devez gérer les éventuelles clés en double dans les sous-tableaux. Une réponse similaire dans une question connexe: PHP Parcourez un tableau multidimensionnel tout en préservant les clés

Je ne suis pas particulièrement sûr, mais je l'ai déjà testé dans le passé: le RecurisiveIteratorutilise la récursivité, donc cela dépend de ce dont vous avez vraiment besoin. Il devrait également être possible de créer un itérateur récursif basé sur des piles:

foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
{
    echo "** ($key) $value\n";
}

Démo

Je n'ai pas réussi jusqu'ici à implémenter la pile sur RecursiveIteratorlaquelle je pense que c'est une bonne idée.

hakre
la source
+1 pour la fonction array_flatten exceptionnelle. J'ai dû ajouter if(!empty($value)){$flat[] = $value}à l'intérieur de l'instruction else pour empêcher l'ajout de vide au tableau de résultats. Fonction géniale!
Alex Sarnowski
19

Réponse simple et à une ligne .

function flatten_array(array $array)
{
    return iterator_to_array(
         new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)));
}

Usage:

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

print_r( flatten_array($array) );

Sortie (en PsySH):

Array
(
    [name] => Allen Linatoc
    [age] => 21
    [0] => Call of Duty
    [1] => Titanfall
    [2] => Far Cry
)

Maintenant, c'est à vous de voir comment vous allez gérer les clés. À votre santé


EDIT (01/03/2017)

Citant la préoccupation / le problème de Nigel Alderton :

Juste pour clarifier, cela préserve les clés (même numériques) afin que les valeurs qui ont la même clé soient perdues. Par exemple $array = ['a',['b','c']]devient Array ([0] => b, [1] => c ). Le 'a'est perdu car 'b'possède également une clé de0

Citant la réponse de Svish :

Ajoutez simplement false comme deuxième paramètre ($use_keys)à l' appel iterator_to_array

Allen Linatoc
la source
Juste pour clarifier, cela préserve les clés (même numériques) afin que les valeurs qui ont la même clé soient perdues. Par exemple $array = ['a',['b','c']]devient Array ([0] => b, [1] => c ). Le 'a'est perdu car 'b'possède également une clé de 0.
Nigel Alderton
1
@NigelAlderton Il suffit d'ajouter falsecomme deuxième paramètre ( $use_keys) à l' iterator_to_arrayappel.
Svish
18

Utilise la récursivité. Avec un peu de chance, en voyant à quel point c'est non complexe, votre peur de la récursivité se dissipera une fois que vous verrez à quel point ce n'est pas complexe.

function flatten($array) {
    if (!is_array($array)) {
        // nothing to do if it's not an array
        return array($array);
    }

    $result = array();
    foreach ($array as $value) {
        // explode the sub-array, and add the parts
        $result = array_merge($result, flatten($value));
    }

    return $result;
}


$arr = array('foo', array('nobody', 'expects', array('another', 'level'), 'the', 'Spanish', 'Inquisition'), 'bar');
echo '<ul>';
foreach (flatten($arr) as $value) {
    echo '<li>', $value, '</li>';
}
echo '<ul>';

Production:

<ul><li>foo</li><li>nobody</li><li>expects</li><li>another</li><li>level</li><li>the</li><li>Spanish</li><li>Inquisition</li><li>bar</li><ul>
nilamo
la source
1
Je ne crains pas la récursivité, je veux juste apprendre d'autres façons de faire de même.
Alix Axel
13
+1 pour cette récursivité: Espérons qu'en voyant à quel point elle n'est pas complexe, votre peur de la récursion se dissipera une fois que vous verrez à quel point elle n'est pas complexe.
Tiberiu-Ionuț Stan
1
OK, c'est fini pour moi. Comment cela est possible, cette réponse ("Je ne crains pas la récursivité") a trois ans et demi de plus (24 août 09) que la déclaration initiale ("(...) votre peur de la récursion se dissipera (... ) "), faite le 5 février 13?
trejder
18

Je pensais juste souligner que c'est un pli, donc array_reduce peut être utilisé:

array_reduce($my_array, 'array_merge', array());

EDIT: Notez que cela peut être composé pour aplatir n'importe quel nombre de niveaux. Nous pouvons le faire de plusieurs manières:

// Reduces one level
$concat   = function($x) { return array_reduce($x, 'array_merge', array()); };

// We can compose $concat with itself $n times, then apply it to $x
// This can overflow the stack for large $n
$compose  = function($f, $g) {
    return function($x) use ($f, $g) { return $f($g($x)); };
};
$identity = function($x) { return $x; };
$flattenA = function($n) use ($compose, $identity, $concat) {
    return  function($x) use ($compose, $identity, $concat, $n) {
        return ($n === 0)? $x
                         : call_user_func(array_reduce(array_fill(0, $n, $concat),
                                                       $compose,
                                                       $identity),
                                          $x);
    };
};

// We can iteratively apply $concat to $x, $n times
$uncurriedFlip     = function($f) {
    return  function($a, $b) use ($f) {
        return $f($b, $a);
    };
};
$iterate  = function($f) use ($uncurriedFlip) {
    return  function($n) use ($uncurriedFlip, $f) {
    return  function($x) use ($uncurriedFlip, $f, $n) {
        return ($n === 0)? $x
                         : array_reduce(array_fill(0, $n, $f),
                                        $uncurriedFlip('call_user_func'),
                                        $x);
    }; };
};
$flattenB = $iterate($concat);

// Example usage:
$apply    = function($f, $x) {
    return $f($x);
};
$curriedFlip = function($f) {
    return  function($a) use ($f) {
    return  function($b) use ($f, $a) {
        return $f($b, $a);
    }; };
};

var_dump(
    array_map(
        call_user_func($curriedFlip($apply),
                       array(array(array('A', 'B', 'C'),
                                   array('D')),
                             array(array(),
                                   array('E')))),
        array($flattenA(2), $flattenB(2))));

Bien sûr, nous pourrions également utiliser des boucles, mais la question demande une fonction de combinaison le long des lignes de array_map ou array_values.

Warbo
la source
Multidimensionnel! = Bidimensionnel.
Alix Axel
@atamur Cela fonctionne sur PHP 5.3+. Comme indiqué dans le journal des modifications de array_reduce, $ initial ne pouvait être qu'un entier avant 5.3, puis il était autorisé à être "mélangé" (c'est-à-dire tout ce que votre fonction de réduction prend en charge)
Warbo
1
@AlixAxel Vous avez raison de dire que multidimensionnel! = Bidimensionnel, mais cela peut être composé pour aplatir n'importe quel nombre de niveaux. Une bonne conséquence de la composition des plis est qu'elle obéit à une limite fixe; si j'ai un tableau imbriqué à 5 niveaux, je peux le foldfaire en 4 niveaux, ou fold . foldobtenir 3 niveaux, ou fold . fold . foldobtenir 2 niveaux, etc. Cela empêche également les bogues de se cacher; par exemple. si je veux aplatir un tableau 5D mais que je reçois un tableau 4D, l'erreur se déclenchera immédiatement.
Warbo
J'adore cette solution, pour les tableaux bidimensionnels. Convient parfaitement au projet de loi.
Tom Auger
Je suis d'accord que votre définition de niveau unique est la meilleure réponse, elle est également merveilleusement soignée. Cependant, je pense que vous l'avez mal nommé $concat, je pense que vous devriez simplement l'appeler $flatten. array_mergeest l'équivalent php de concat. J'ai essayé d'être array_concatajouté comme alias pour array_merge.
icc97
9

Aplatit uniquement les tableaux bidimensionnels:

$arr = [1, 2, [3, 4]];
$arr = array_reduce($arr, function ($a, $b) {
     return array_merge($a, (array) $b);
}, []);

// Result: [1, 2, 3, 4]
artnikpro
la source
5

Cette solution est non récursive. Notez que l'ordre des éléments sera quelque peu mélangé.

function flatten($array) {
    $return = array();
    while(count($array)) {
        $value = array_shift($array);
        if(is_array($value))
            foreach($value as $sub)
                $array[] = $sub;
        else
            $return[] = $value;
    }
    return $return;
}
trop de php
la source
1
Idée intelligente, mais il y a un bug. "$ array [] = $ value" n'ajoute pas tous les éléments de $ value à $ array, il ajoute simplement $ value lui-même. Si vous exécutez ce code, il bouclera indéfiniment.
Todd Owen
Oui, shiftingla valeur du tableau et son ajout à la fin n'a pas beaucoup de sens. Je suppose que tu le voulais à la array_merge()place?
décomposition
4

Je crois que c'est la solution la plus propre sans utiliser de mutations ni de classes inconnues.

<?php

function flatten($array)
{
    return array_reduce($array, function($acc, $item){
        return array_merge($acc, is_array($item) ? flatten($item) : [$item]);
    }, []);
}


// usage
$array = [1, 2, [3, 4], [5, [6, 7]], 8, 9, 10];
print_r(flatten($array));
Dariush Alipour
la source
3

Essayez la fonction simple suivante:

function _flatten_array($arr) {
  while ($arr) {
    list($key, $value) = each($arr); 
    is_array($value) ? $arr = $value : $out[$key] = $value;
    unset($arr[$key]);
  }
  return (array)$out;
}

Donc à partir de là:

array (
  'und' => 
  array (
    'profiles' => 
    array (
      0 => 
      array (
        'commerce_customer_address' => 
        array (
          'und' => 
          array (
            0 => 
            array (
              'first_name' => 'First name',
              'last_name' => 'Last name',
              'thoroughfare' => 'Address 1',
              'premise' => 'Address 2',
              'locality' => 'Town/City',
              'administrative_area' => 'County',
              'postal_code' => 'Postcode',
            ),
          ),
        ),
      ),
    ),
  ),
)

vous obtenez:

array (
  'first_name' => 'First name',
  'last_name' => 'Last name',
  'thoroughfare' => 'Address 1',
  'premise' => 'Address 2',
  'locality' => 'Town/City',
  'administrative_area' => 'County',
  'postal_code' => 'Postcode',
)
Kenorb
la source
vous devriez peut-être vérifier votre fonction ... semble ne pas fonctionner comme prévu
Emiliano
@Emiliano Essayez de poser une nouvelle question, peut-être que vos données d'entrée sont différentes, donc cela ne fonctionnera pas dans votre cas particulier.
kenorb
nous avons quelques problèmes, chacun est une fonction obsolète, vous pouvez améliorer ce point, vous n'étiez pas un nouveau gars ici, vous devriez le savoir en second si votre code fonctionne avec une version spécifique de php le dire en troisième sinon travailler avec toutes les données le dire
Emiliano
2

L'astuce consiste à passer les tableaux source et destination par référence.

function flatten_array(&$arr, &$dst) {
    if(!isset($dst) || !is_array($dst)) {
        $dst = array();
    }
    if(!is_array($arr)) {
        $dst[] = $arr;
    } else {
        foreach($arr as &$subject) {
            flatten_array($subject, $dst);
        }
    }
}

$recursive = array('1', array('2','3',array('4',array('5','6')),'7',array(array(array('8'),'9'),'10')));
echo "Recursive: \r\n";
print_r($recursive);
$flat = null;
flatten_array($recursive, $flat);

echo "Flat: \r\n";
print_r($flat);

// If you change line 3 to $dst[] = &$arr; , you won't waste memory,
// since all you're doing is copying references, and imploding the array 
// into a string will be both memory efficient and fast:)

echo "String:\r\n";
echo implode(',',$flat);
Rick Garcia
la source
2
/**
 * For merging values of a multidimensional array into one 
 *
 * $array = [
 *     0 => [
 *         0 => 'a1',
 *         1 => 'b1',
 *         2 => 'c1',
 *         3 => 'd1'
 *     ],
 *     1 => [
 *         0 => 'a2',
 *         1 => 'b2',
 *         2 => 'c2',
 *     ]
 * ];
 *
 * becomes : 
 *
 * $array = [
 *     0 => 'a1',
 *     1 => 'b1',
 *     2 => 'c1',
 *     3 => 'd1',
 *     4 => 'a2',
 *     5 => 'b2',
 *     6 => 'c2',
 *     
 * ]
 */
array_reduce
(
    $multiArray
    , function ($lastItem, $currentItem) {
        $lastItem = $lastItem ?: array();
        return array_merge($lastItem, array_values($currentItem));
    }
);

Extrait de Gist

Arsham
la source
Cela semble ne prendre en charge que les tableaux bidimensionnels.
Alix Axel
Vous avez raison. Il est inutile de l'utiliser. Je pense que la meilleure solution est la réponse "trop ​​de php".
Arsham
2

Si vous n'aimez vraiment pas une récursivité ... essayez plutôt de changer :)

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
$o = [];
for ($i=0; $i<count($a); $i++) {
    if (is_array($a[$i])) {
        array_splice($a, $i+1, 0, $a[$i]);
    } else {
        $o[] = $a[$i];
    }
}

Remarque: dans cette version simple, cela ne prend pas en charge les clés de tableau.

BurninLeo
la source
c'est une approche intéressante. contrairement aux autres solutions, il édite le tableau d'origine ($ a). Si vous le remplacez par un continue, c'est un peu plus rapide.
pcarvalho
2

Que diriez-vous d'utiliser un générateur récursif? https://ideone.com/d0TXCg

<?php

$array = [
    'name' => 'Allen Linatoc',
    'profile' => [
        'age' => 21,
        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
    ]
];

foreach (iterate($array) as $item) {
    var_dump($item);
};

function iterate($array)
{
    foreach ($array as $item) {
        if (is_array($item)) {
            yield from iterate($item);
        } else {
            yield $item;
        }
    }
}
Andriy
la source
1

Pour php 5.2

function flatten(array $array) {
    $result = array();

    if (is_array($array)) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                $result = array_merge($result, flatten($v));
            } else {
                $result[] = $v;
            }
        }
    }

    return $result;
}
Alexei T
la source
Veuillez inclure une explication avec cette réponse de code uniquement.
mickmackusa
1

Cette version peut faire des niveaux profonds, peu profonds ou un nombre spécifique de niveaux:

/**
 * @param  array|object $array  array of mixed values to flatten
 * @param  int|boolean  $level  0:deep, 1:shallow, 2:2 levels, 3...
 * @return array
 */
function flatten($array, $level = 0) {
    $level = (int) $level;
    $result = array();
    foreach ($array as $i => $v) {
        if (0 <= $level && is_array($v)) {
            $v = flatten($v, $level > 1 ? $level - 1 : 0 - $level);
            $result = array_merge($result, $v);
        } elseif (is_int($i)) {
            $result[] = $v;
        } else {
            $result[$i] = $v; 
        }
    }
    return $result;
}
ryanve
la source
Au-delà d'expliquer ce que cet extrait peut faire, veuillez expliquer aux futurs chercheurs comment il fonctionne.
mickmackusa
1

Parce que le code ici semble effrayant. Voici une fonction qui convertira également un tableau multidimensionnel en syntaxe compatible avec le format html, mais qui est plus facile à lire.

/**
 * Flattens a multi demensional array into a one dimensional
 * to be compatible with hidden html fields.
 *
 * @param array $array
 *  Array in the form:
 *  array(
 *    'a' => array(
 *      'b' => '1'
 *    )
 *  )
 *
 * @return array
 *  Array in the form:
 *  array(
 *    'a[b]' => 1,
 *  )
 */
function flatten_array($array) {
  // Continue until $array is a one-dimensional array.
  $continue = TRUE;
  while ($continue) {
    $continue = FALSE;

    // Walk through top and second level of $array and move 
    // all values in the second level up one level.
    foreach ($array as $key => $value) {
      if (is_array($value)) {
        // Second level found, therefore continue.
        $continue = TRUE;

        // Move each value a level up.
        foreach ($value as $child_key => $child_value) {
          $array[$key . '[' . $child_key . ']'] = $child_value;
        }

        // Remove second level array from top level.
        unset($array[$key]);
      }
    }
  }

  return $array;
}
Gellweiler
la source
1

Ceci peut être réalisé en utilisant array_walk_recursive

$a = array(1,2,array(3,4, array(5,6,7), 8), 9);
array_walk_recursive($a, function($v) use (&$r){$r[]=$v;});
print_r($r);

Exemple de travail: - https://3v4l.org/FpIrG

Rakesh Jakhar
la source
0

Voici ma solution, en utilisant une référence:

function arrayFlatten($array_in, &$array_out){

    if(is_array($array_in)){
        foreach ($array_in as $element){
               arrayFlatten($element, $array_out);
        }
    }
    else{
        $array_out[] = $array_in; 
    }
}

$arr1 = array('1', '2', array(array(array('3'), '4', '5')), array(array('6')));

arrayFlatten($arr1, $arr2);

echo "<pre>";
print_r($arr2);
echo "</pre>";
Martyn Shutt
la source
Veuillez inclure des explications sur le fonctionnement de votre extrait de code et pourquoi c'est une bonne idée. Les réponses de code uniquement sont de faible valeur sur StackOverflow car elles font un mauvais travail d'éduquer / d'autonomiser le PO et les futurs chercheurs. N'oubliez pas que nous ne parlons jamais UNIQUEMENT au PO; les anciennes pages sont utilisées pour fermer de nouvelles pages, les pages doivent donc être suffisamment informatives pour résoudre également les problèmes des futurs demandeurs.
mickmackusa
0
<?php
//recursive solution

//test array
$nested_array = [[1,2,[3]],4,[5],[[[6,[7=>[7,8,9,10]]]]]];

/*-----------------------------------------
function call and return result to an array
------------------------------------------*/
$index_count = 1;
$flatered_array = array();
$flatered_array = flat_array($nested_array, $index_count);

/*-----------------------------------------
Print Result
-----------------------------------------*/
echo "<pre>";
print_r($flatered_array);


/*-----------------------------------------
function to flaten an array 
-----------------------------------------*/
function flat_array($nested_array, & $index_count, & $flatered_array) {

  foreach($nested_array AS $key=>$val) {
      if(is_array($val)) {
        flat_array($val, $index_count, $flatered_array);
      }
      else {
        $flatered_array[$index_count] = $val;
        ++$index_count;
      }      
  }

return $flatered_array;
}
?>
Furqan libéré
la source
0

Voici une approche simpliste:

$My_Array = array(1,2,array(3,4, array(5,6,7), 8), 9);

function checkArray($value) {
    foreach ($value as $var) {
        if ( is_array($var) ) {
            checkArray($var);
        } else {
            echo $var;
        }
    }
}

checkArray($My_Array);
Jack
la source
0

Quiconque cherche une solution vraiment propre à cela; voici une option:

$test_array = array(
    array('test' => 0, 0, 0, 0),
    array(0, 0, 'merp' => array('herp' => 'derp'), 0),
    array(0, 0, 0, 0),
    array(0, 0, 0, 0)
);
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($test_array));
var_dump( iterator_to_array($it, false) ) ; 

Impressions

 0 0 0 0 0 0 derp 0 0 0 0 0 0 0 0 0
Lewis
la source
0

Je poste juste une autre solution)

function flatMultidimensionalArray(array &$_arr): array
{
    $result = [];
    \array_walk_recursive($_arr, static function (&$value, &$key) use (&$result) {
        $result[$key] = $value;
    });

    return $result;
}
James Bond
la source
0

Si vous souhaitez également conserver vos clés, c'est la solution.

function reduce(array $array) {
    $return = array();
    array_walk_recursive($array, function($value, $key) use (&$return) { $return[$key] = $value; });
    return $return;
}

Malheureusement, il ne produit que des tableaux imbriqués finaux, sans touches centrales. Donc pour l'exemple suivant:

$array = array(
    'sweet' => array(
        'a' => 'apple',
        'b' => 'banana'),
    'sour' => 'lemon'); 
print_r(flatten($fruits));

La sortie est:

Array
(
    [a] => apple
    [b] => banana
    [sour] => lemon
)
Tajni
la source
-1

J'avais besoin de représenter un tableau multidimensionnel PHP au format d'entrée HTML.

$test = [
    'a' => [
        'b' => [
            'c' => ['a', 'b']
        ]
    ],
    'b' => 'c',
    'c' => [
        'd' => 'e'
    ]
];

$flatten = function ($input, $parent = []) use (&$flatten) {
    $return = [];

    foreach ($input as $k => $v) {
        if (is_array($v)) {
            $return = array_merge($return, $flatten($v, array_merge($parent, [$k])));
        } else {
            if ($parent) {
                $key = implode('][', $parent) . '][' . $k . ']';

                if (substr_count($key, ']') != substr_count($key, '[')) {
                    $key = preg_replace('/\]/', '', $key, 1);
                }
            } else {
                $key = $k;
            }           

            $return[$key] = $v;
        }
    }

    return $return;
};

die(var_dump( $flatten($test) ));

array(4) {
  ["a[b][c][0]"]=>
  string(1) "a"
  ["a[b][c][1]"]=>
  string(1) "b"
  ["b"]=>
  string(1) "c"
  ["c[d]"]=>
  string(1) "e"
}
Gajus
la source
@AlixAxel Comment ce commentaire est-il relatif? Mauvais article ..?
Gajus
Non. Je pensais que c'était assez similaire à ce que vous faites et j'ai décidé de le partager, je pense que la seule différence est que ma représentation est également valide en PHP - du formulaire $var['a']['b']['c'][0] = 'a'; ....
Alix Axel
J'avais intentionnellement besoin d'une sortie HTML. Mais merci pour le partage.
Gajus
1
Je pense que c'est la bonne réponse à la mauvaise question. Lorsque vous répondez, veuillez essayer de répondre à la question telle qu'elle est posée - sinon les pages peuvent s'écarter du problème central et laisser les futurs chercheurs confus.
mickmackusa
-1

Si vous avez un tableau d'objets et que vous souhaitez l'aplatir avec un nœud, utilisez simplement cette fonction:

function objectArray_flatten($array,$childField) {
    $result = array();
    foreach ($array as $node)
    {
        $result[] = $node;
        if(isset($node->$childField))
        {
            $result = array_merge(
                $result, 
                objectArray_flatten($node->$childField,$childField)
            );
            unset($node->$childField);
        }

    }
    return $result;
}
حسین شکرزاده
la source