web-dev-qa-db-fra.com

Comment "aplatir" un tableau multi-dimensionnel en un simple en PHP?

C'est probablement une question de débutant, mais je consulte déjà la documentation depuis plus longtemps et je ne trouve aucune solution. Je pensais pouvoir utiliser implode pour chaque dimension, puis rassembler ces chaînes avec str_split pour créer un nouveau tableau simple. Cependant, je ne sais jamais si le modèle de jointure n'est pas aussi dans les valeurs et donc, après avoir utilisé str_split, mes valeurs d'origine pourraient se briser.

Existe-t-il quelque chose comme combine($array1, $array2) pour les tableaux dans un tableau multidimensionnel?

68
Adriana

Utilisez array_walk_recursive

<?php

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

$objTmp = (object) array('aFlat' => array());

array_walk_recursive($aNonFlat, create_function('&$v, $k, &$t', '$t->aFlat[] = $v;'), $objTmp);

var_dump($objTmp->aFlat);

/*
array(11) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
  [4]=>
  int(5)
  [5]=>
  int(6)
  [6]=>
  int(7)
  [7]=>
  int(8)
  [8]=>
  int(9)
  [9]=>
  int(10)
  [10]=>
  int(11)
}
*/

?>

Testé avec PHP 5.5.9-1ubuntu4.24 (cli) (construit le 16 mars 2018 à 12:32:06)

41
Luc M
$array  = your array

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

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

REF: http://php.net/manual/en/function.call-user-func-array.php

Voici une autre solution (fonctionne avec un tableau multi-dimensionnel):

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);
115
Prasanth Bendra

Ceci est une ligne, SUPER facile à utiliser:

$result = array();
array_walk_recursive($original_array,function($v) use (&$result){ $result[] = $v; });

Il est très facile à comprendre, à l’intérieur de la fonction/fermeture anonyme. $v est la valeur de votre $original_array.

44
Arnold Roa
// $array = your multidimensional array

$flat_array = array();

foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $k=>$v){

$flat_array[$k] = $v;

}

Également documenté: http://www.phpro.org/examples/Flatten-Array.html

19
upallnite
function flatten_array($array, $preserve_keys = 0, &$out = array()) {
    # Flatten a multidimensional array to one dimension, optionally preserving keys.
    #
    # $array - the array to flatten
    # $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
    # $out - internal use argument for recursion
    foreach($array as $key => $child)
        if(is_array($child))
            $out = flatten_array($child, $preserve_keys, $out);
        elseif($preserve_keys + is_string($key) > 1)
            $out[$key] = $child;
        else
            $out[] = $child;
    return $out;
}
5
chaos

Une autre méthode de PHP commentaires utilisateur (simplifié) et ici :

function array_flatten_recursive($array) { 
   if (!$array) return false;
   $flat = array();
   $RII = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
   foreach ($RII as $value) $flat[] = $value;
   return $flat;
}

Le gros avantage de cette méthode est qu’elle suit la profondeur de la récursion, si vous en avez besoin tout en étant aplatie.
Cela produira:

$array = array( 
    'A' => array('B' => array( 1, 2, 3)), 
    'C' => array(4, 5) 
); 
print_r(array_flatten_recursive($array)); 

#Returns: 
Array ( 
    [0] => 1 
    [1] => 2 
    [2] => 3 
    [3] => 4 
    [4] => 5 
)
5
SamGoody

Avec PHP 7, vous pouvez utiliser des générateurs et leur délégation (yield from) pour aplatir un tableau:

function array_flatten_iterator (array $array) {
    foreach ($array as $value) {
        if (is_array($value)) {
            yield from array_flatten_iterator($value);
        } else {
            yield $value;
        }
    }
}

function array_flatten (array $array) {
    return iterator_to_array(array_flatten_iterator($array), false);
}

Exemple:

$array = [
    1,
    2,
    [
        3,
        4,
        5,
        [
            6,
            7
        ],
        8,
        9,
    ],
    10,
    11,
];    

var_dump(array_flatten($array));

http://3v4l.org/RU30W

4
kelunik

En PHP> = 5.3 et basé sur la réponse de Luc M (le premier), vous pouvez utiliser des fermetures comme celle-ci

array_walk_recursive($aNonFlat, function(&$v, $k, &$t){$t->aFlat[] = $v;}, $objTmp);

J'aime cela car je n'ai pas à entourer le code de la fonction avec des guillemets, comme lors de l'utilisation de create_function ()

4
hisa_py

Une solution non récursive (mais destructrice d'ordre):

function flatten($ar) {
    $toflat = array($ar);
    $res = array();

    while (($r = array_shift($toflat)) !== NULL) {
        foreach ($r as $v) {
            if (is_array($v)) {
                $toflat[] = $v;
            } else {
                $res[] = $v;
            }
        }
    }

    return $res;
}
4
phihag

Si vous avez spécifiquement un tableau de tableaux qui ne va pas plus loin qu'un niveau (un cas d'utilisation que je trouve commun), vous pouvez vous en sortir avec array_merge et l'opérateur Splat.

<?php

$notFlat = [[1,2],[3,4]];
$flat = array_merge(...$notFlat);
var_dump($flat);

Sortie:

array(4) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
}

L'opérateur Splat modifie efficacement le tableau de tableaux en une liste de tableaux comme arguments pour array_merge.

2
Josh Johnson

Utilisation de fonctions d’ordre supérieur (note: j’utilise des fonctions anonymes inline , apparues dans PHP 5.3): 

function array_flatten($array) {
    return array_reduce(
        $array,
        function($prev, $element) {
            if (!is_array($element))
                $prev[] = $element;
            else
                $prev = array_merge($prev, array_flatten($element));
            return $prev;
        },
        array()
    );
}
2
Paul d'Aoust

Si vous acceptez de perdre des clés de tableau, vous pouvez aplatir un tableau multidimensionnel en utilisant une fermeture récursive en tant que rappel utilisant array_values ​​(), en vous assurant que ce rappel est un paramètre pour array_walk (), comme suit.

<?php  

$array = [1,2,3,[5,6,7]];
$nu_array = null;
$callback = function ( $item ) use(&$callback, &$nu_array) {
    if (!is_array($item)) {
    $nu_array[] = $item;
    }
    else
    if ( is_array( $item ) ) {
     foreach( array_values($item) as $v) {
         if ( !(is_array($v))) {
             $nu_array[] = $v;
         }
         else
         { 
             $callback( $v );
         continue;
         }    
     }
    }
};

array_walk($array, $callback);
print_r($nu_array);

L'inconvénient de l'exemple précédent est qu'il implique l'écriture de beaucoup plus de code que la solution suivante qui utilise array_walk_recursive () avec un rappel simplifié:

<?php  

$array = [1,2,3,[5,6,7]];

$nu_array = [];
array_walk_recursive($array, function ( $item ) use(&$nu_array )
                     {
                         $nu_array[] = $item;
                     }
);
print_r($nu_array);

Voir code live

Cet exemple semble préférable au précédent, masquant les détails sur la façon dont les valeurs sont extraites d'un tableau multidimensionnel. Bien sûr, l'itération se produit, mais que cela implique une ou plusieurs structures de contrôle, vous ne le saurez qu'en parcourant array.c. Étant donné que la programmation fonctionnelle met l’accent sur les entrées et les sorties plutôt que sur l’obtention d’un résultat, on peut certainement rester indifférent à la manière dont se déroule l’itération en coulisse, c’est-à-dire jusqu’à ce que l’employeur potentiel pose une telle question. 

1
slevy1
/*consider $mArray as multidimensional array and $sArray as single dimensional array
this code will ignore the parent array
*/

function flatten_array2($mArray) {
    $sArray = array();

    foreach ($mArray as $row) {
        if ( !(is_array($row)) ) {
            if($sArray[] = $row){
            }
        } else {
            $sArray = array_merge($sArray,flatten_array2($row));
        }
    }
    return $sArray;
}
1
Iman

Une nouvelle approche basée sur l'exemple de fonction précédent soumis par chaos, qui corrige le bogue de réécriture des clés de chaîne dans plusieurs tableaux:

# Flatten a multidimensional array to one dimension, optionally preserving keys.
# $array - the array to flatten
# $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
# $out - internal use argument for recursion

function flatten_array($array, $preserve_keys = 2, &$out = array(), &$last_subarray_found) 
{
        foreach($array as $key => $child)
        {
            if(is_array($child))
            {
                $last_subarray_found = $key;
                $out = flatten_array($child, $preserve_keys, $out, $last_subarray_found);
            }
            elseif($preserve_keys + is_string($key) > 1)
            {
                if ($last_subarray_found)
                {
                    $sfinal_key_value = $last_subarray_found . "_" . $key;
                }
                else
                {
                    $sfinal_key_value = $key;
                }
                $out[$sfinal_key_value] = $child;
            }
            else
            {
                $out[] = $child;
            }
        }

        return $out;
}

Example:
$newarraytest = array();
$last_subarray_found = "";
$this->flatten_array($array, 2, $newarraytest, $last_subarray_found);
1
xtrm

vous pouvez essayer ceci:

function flat_an_array($a)
{
    foreach($a as $i)
    {
        if(is_array($i)) 
        {
            if($na) $na = array_merge($na,flat_an_array($i));
            else $na = flat_an_array($i);
        }
        else $na[] = $i;
    }
    return $na;
}
1
TomSawyer

J'ai trouvé un moyen simple de convertir un tableau à plusieurs niveaux en un . J'utilise la fonction "http_build_query" qui convertit le tableau en une chaîne d'URL . Ensuite, divisez la chaîne avec exploser et décoder la valeur.

Voici un échantillon.

$converted = http_build_query($data);
$rows = explode('&', $converted);
$output = array();
foreach($rows AS $k => $v){
   list($kk, $vv) = explode('=', $v);
   $output[ urldecode($kk) ] =  urldecode($vv);
}
return $output;
0

Approche simple..Voir via récursivité ..

<?php

function flatten_array($simple){
static $outputs=array();
foreach ( $simple as $value)
{
if(is_array($value)){
    flatten_array($value);
}
else{
    $outputs[]=$value;
}

}
return $outputs;
}

$eg=['s'=>['p','n'=>['t']]];
$out=flatten_array($eg);
print_r($out);

?>
0
Paras Agarwal

Vous pouvez utiliser la fonction flatten from from Bibliothèque PHP non standard (NSPL) . Cela fonctionne avec les tableaux et toutes les structures de données itérables.

assert([1, 2, 3, 4, 5, 6, 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]]));
0
Ihor Burlachenko