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().


17
Pourquoi éviter la récursivité?
JorenB


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 

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;
}

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


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);

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.


+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


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>

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.


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]

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;
}

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));

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',
)

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);

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


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.


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;
        }
    }
}

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;
}

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;
}

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;
}

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


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>";

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;
}
?>

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);

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

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;
}

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
)

-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"
}


@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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.