Wie wird ein mehrdimensionales Array abgeflacht?


259

Ist es in PHP möglich, ein (zweidimensionales) Array ohne Verwendung von Rekursion oder Referenzen zu reduzieren?

Ich interessiere mich nur für die Werte, damit die Schlüssel ignoriert werden können. Ich denke in den Zeilen von array_map()und array_values().


17
Warum Rekursion vermeiden?
JorenB


4
Sie können nicht mit allen Elementen eines beliebig tiefen Arrays ohne Rekursion etwas tun (Sie können es als Iteration tarnen, aber Kartoffel, Potahto.) Wenn Sie nur vermeiden möchten, den Code für die Rekursionsbehandlung selbst zu schreiben, verwenden Sie dk2.php.net/ manual / de / function.array-walk-recursive.php mit einem Rückruf, der das Element einem verfügbaren Array hinzufügt (verwenden Sie global, den Parameter userdata, ordnen Sie alles in eine Klasse ein und verweisen Sie auf $ this usw.)
Michael Madsen

@JorenB: Ich würde gerne sehen, dass eine Implementierung archiviert werden kann.
Alix Axel

Schauen Sie sich die Abflachungsfunktion von Nspl an . Sie können damit auch eine Tiefe angeben.
Ihor Burlachenko

Antworten:


276

Sie können die Standard-PHP-Bibliothek (SPL) verwenden , um die Rekursion "auszublenden".

$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, " ";
}

druckt

1 2 3 4 5 6 7 8 9 

351
Bin ich der einzige, der denkt, dass 'RecursiveIteratorIterator' ein alberner Name ist?
Nilamo

45
Es ist eher "logisch" als "eingängig". Nicht alles kann einen fantastischen Namen wie JOGL, Knol oder Azure haben :-)
VolkerK

7
Dies funktioniert nicht für leere Arrays als Kinder. Sie werden als Eltern zurückgegeben.
hakre

45
iterator_to_array($it, false)vermeidet die Notwendigkeit für die foreach.
Alix Axel

3
Aufbauend auf dem, was andere präsentierten, konnte ich diesen kleinen Helfer herstellen: Ich function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }hoffe, das hilft anderen.
Mike S.

295

Ab PHP 5.3 scheint die kürzeste Lösung array_walk_recursive()die neue Closures-Syntax zu sein:

function flatten(array $array) {
    $return = array();
    array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
    return $return;
}

33
Wenn Sie Schlüssel möchten, Funktion flatten (Array $ Array) {$ return = Array (); array_walk_recursive ($ array, function ($ a, $ b) use (& $ return) {$ return [$ b] = $ a;}); return $ return; }
Brendon-Van-Heyzen

Kannst du dies umschreiben, um es mit PHP 5.2 zu verwenden?
Alex

2
@ Alex leider benötigen Sie die useSyntax, damit dies funktioniert, array_walk_recursiveda es den optionalen $userdataParameter nicht als Referenz akzeptiert
Tim Seguine

1
Sieht so aus, als würde es für solche Arrays gut funktionieren -> ideone.com/DsmApP Aber nicht für solche -> ideone.com/5Kltva Oder bin ich es?
Sebastian Piskorski

2
@Sebastian Piskorski, weil Ihre Werte wie Schlüssel behandelt werden. Sobald Sie also Ihr eigenes Schlüssel => Wertepaar in ein Array einfügen, werden Ihre Array-Werte an der ersten Indexposition wie Schlüssel ohne Werte behandelt, und weil Schlüssel haben Um eindeutig zu sein, wenn zwei Schlüssel übereinstimmen, werden Ihre Werte demselben Schlüssel hinzugefügt. Eine einfache Lösung wäre, zuerst das Array zu sortieren. Dies ist ein Verhalten, das PHP innewohnt.
Martyn Shutt

92

Lösung für zweidimensionales Array

Bitte versuchen Sie dies:

$array  = your array

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

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

EDIT: 21-Aug-13

Hier ist die Lösung, die für mehrdimensionale Arrays funktioniert:

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

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


Vielen Dank, der erste arbeitete an einem Array, das ich von PDO erhalten hatte, während die anderen Lösungen dies nicht taten.
JAL

7
Dies ist eine schlechte Strategie. call_user_func_array('array_merge', [])(Beachten Sie das leere Array) gibt null zurück und löst einen PHP-Warnfehler aus. Es ist eine clevere Lösung, wenn Sie sicher sind, dass Ihr Array nicht leer ist, aber das ist keine verbreitete Annahme, die viele machen können.
Ziege

Das OP forderte ausdrücklich nicht rekursive Lösungen.
Élektra

Wow, coole 2d Flattern! Aber um eine Benachrichtigung zu verhindern, verwenden Sie einfach$result = $array ?call_user_func_array('array_merge', $array) : [];
Alexander Goncharov

cool bruh, aber hast du nicht zufällig eine gegenfunktion array-deflatten?
FantomX1

64

In PHP 5.6 und höher können Sie zweidimensionale Arrays mit array_mergereduzieren, nachdem Sie das äußere Array mit dem ...Operator entpackt haben . Der Code ist einfach und klar.

array_merge(...$a);

Dies funktioniert auch mit der Sammlung von assoziativen Arrays.

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

Es funktioniert jedoch nicht, wenn das äußere Array nicht numerische Schlüssel enthält. In diesem Fall müssen Sie array_valueszuerst anrufen .

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

Update: Basierend auf einem Kommentar von @MohamedGharib

Dies löst einen Fehler aus, wenn das äußere Array leer ist, da array_mergees mit null Argumenten aufgerufen würde. Dies kann vermieden werden, indem als erstes Argument ein leeres Array hinzugefügt wird.

array_merge([], ...$a);

1
Dies funktioniert NUR, wenn jedes Element des Arrays ein Array ist. Wenn das Array gemischte Typen wie Skalare enthält, tritt ein Fehler auf.
Otheus

@Otheus Das liegt daran, dass die obige Lösung keine Rekursion verwendet. Wie Sie sagten, erfordert es ein Array von Array. Auf der positiven Seite sollte dies jedoch viel schneller sein als bei den anderen Methoden, da es keinen zusätzlichen Overhead für die Funktionsaufrufe gibt.
Joyce Babu

2
Wird einen Fehler auslösen, wenn das äußere Array leer ist, könnte vermeidbar sein, wenn es mit einem leeren Array kombiniert wirdarray_merge([], ...$a);
Mohamed Gharib

@ MohamedGharib Schöner Fang.
Joyce Babu

Wenn Sie assoziative Arrays verwenden, können Sie diese Lösung überprüfen. Stackoverflow.com/questions/40663687/…
alex

24

Um die Rekursion zu reduzieren (wie Sie es gewünscht haben), können Sie einen Stapel verwenden . Natürlich können Sie dies in eine eigene Funktion umsetzen array_flatten. Das Folgende ist eine Version, die ohne Schlüssel funktioniert:

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

Elemente werden in ihrer Reihenfolge verarbeitet. Da Unterelemente auf den Stapel verschoben werden, werden sie als Nächstes verarbeitet.

Es ist auch möglich, Schlüssel zu berücksichtigen. Sie benötigen jedoch eine andere Strategie, um den Stapel zu handhaben. Dies ist erforderlich, da Sie sich mit möglichen doppelten Schlüsseln in den Unterarrays befassen müssen. Eine ähnliche Antwort in einer verwandten Frage: PHP Gehen Sie durch mehrdimensionale Arrays, während Sie die Schlüssel beibehalten

Ich bin mir nicht ganz sicher, aber ich hatte dies in der Vergangenheit getestet: Das RecurisiveIteratorverwendet Rekursion, es hängt also davon ab, was Sie wirklich brauchen. Sollte es möglich sein, einen rekursiven Iterator auch basierend auf Stapeln zu erstellen:

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

Demo

Ich habe es bisher nicht geschafft, den Stack zu implementieren, auf dessen Basis RecursiveIteratorich das für eine gute Idee halte.


+1 für herausragende Funktion array_flatten. Ich musste if(!empty($value)){$flat[] = $value}innerhalb der else-Anweisung hinzufügen , um zu verhindern, dass dem Ergebnisarray Leerzeichen hinzugefügt werden. Tolle Funktion!
Alex Sarnowski

19

Einfache und einzeilige Antwort.

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

Verwendung:

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

print_r( flatten_array($array) );

Ausgabe (in PsySH):

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

Jetzt liegt es ganz bei Ihnen, wie Sie mit den Schlüsseln umgehen. Prost


BEARBEITEN (2017-03-01)

Zitat von Nigel Aldertons Anliegen / Problem:

Zur Verdeutlichung bleiben dabei Schlüssel (auch numerische) erhalten, sodass Werte mit demselben Schlüssel verloren gehen. Zum Beispiel $array = ['a',['b','c']]wird Array ([0] => b, [1] => c ). Das 'a'geht verloren, weil es 'b'auch einen Schlüssel von hat0

Zitat von Svishs Antwort:

Nur falsch als zweite Parameter hinzufügen ($use_keys)an den iterator_to_array Aufruf


Zur Verdeutlichung bleiben dabei Schlüssel (auch numerische) erhalten, sodass Werte mit demselben Schlüssel verloren gehen. Zum Beispiel $array = ['a',['b','c']]wird Array ([0] => b, [1] => c ). Das 'a'geht verloren, weil es 'b'auch einen Schlüssel von hat 0.
Nigel Alderton

1
@NigelAlderton Fügen Sie dem Aufruf einfach falseals zweiten Parameter ( $use_keys) hinzu iterator_to_array.
Svish

18

Verwendet Rekursion. Wenn Sie sehen, wie unkomplex es ist, wird sich Ihre Angst vor Rekursion hoffentlich auflösen, sobald Sie sehen, wie unkomplex es ist.

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

Ausgabe:

<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
Ich habe keine Angst vor Rekursion, ich möchte nur andere Wege lernen, um dasselbe zu tun.
Alix Axel

13
+1 für diese Rekursion: Wenn Sie sehen, wie unkomplex sie ist, wird sich Ihre Angst vor der Rekursion hoffentlich auflösen, sobald Sie sehen, wie unkomplex sie ist.
Tiberiu-Ionuț Stan

1
OK, das ist über mich. Wie es möglich ist, ist diese Antwort ("Ich fürchte keine Rekursion") dreieinhalb Jahre älter (24. August 2009) als die ursprüngliche Aussage ("(...) Ihre Angst vor einer Rekursion wird sich auflösen (... ) "), gemacht am 5. Februar 13?
Trejder

18

Ich dachte nur, ich würde darauf hinweisen, dass dies eine Falte ist, damit array_reduce verwendet werden kann:

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

BEARBEITEN: Beachten Sie, dass dies so zusammengesetzt werden kann, dass eine beliebige Anzahl von Ebenen abgeflacht wird. Wir können dies auf verschiedene Arten tun:

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

Natürlich könnten wir auch Schleifen verwenden, aber die Frage fragt nach einer Kombinatorfunktion nach dem Vorbild von array_map oder array_values.


Mehrdimensional! = Zweidimensional.
Alix Axel

@atamur Dies funktioniert unter PHP 5.3+. Wie im Änderungsprotokoll für array_reduce angegeben, konnte $ initial nur eine Ganzzahl vor 5.3 sein, dann durfte es "gemischt" werden (dh alles, was Ihre Reduktionsfunktion unterstützt)
Warbo

1
@AlixAxel Sie haben Recht, dass mehrdimensional! = Zweidimensional, aber dies kann so zusammengesetzt werden, dass eine beliebige Anzahl von Ebenen abgeflacht wird. Eine schöne Konsequenz beim Zusammenstellen von Falten ist, dass eine feste Grenze eingehalten wird. Wenn ich ein Array habe, das in 5 Ebenen verschachtelt ist, kann ich foldes in 4 Ebenen oder fold . foldin 3 Ebenen oder fold . fold . foldin 2 Ebenen usw. unterteilen. Dadurch wird auch verhindert, dass Fehler versteckt werden. z.B. Wenn ich ein 5D-Array reduzieren möchte, aber ein 4D-Array erhalten möchte, wird der Fehler sofort ausgelöst.
Warbo

Ich liebe diese Lösung für zweidimensionale Arrays. Passt perfekt zur Rechnung.
Tom Auger

Ich bin damit einverstanden, dass Ihre einstufige Definition die beste Antwort ist, sie ist auch wunderbar ordentlich. Wie auch immer ich denke, Sie haben es falsch benannt $concat, ich denke, Sie sollten es einfach nennen $flatten. array_mergeist das PHP-Äquivalent von concat. Ich habe versucht , array_concatals Alias ​​für hinzugefügt zu werden array_merge.
icc97

9

Flacht nur zweidimensionale Arrays ab:

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

// Result: [1, 2, 3, 4]

5

Diese Lösung ist nicht rekursiv. Beachten Sie, dass die Reihenfolge der Elemente etwas gemischt ist.

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
Kluge Idee, aber es gibt einen Fehler. "$ array [] = $ value" fügt nicht alle Elemente von $ value zu $ ​​array hinzu, sondern lediglich $ value selbst. Wenn Sie diesen Code ausführen, wird er auf unbestimmte Zeit wiederholt.
Todd Owen

Ja, shiftingder Wert aus dem Array und das erneute Anhängen an das Ende macht wenig Sinn. Ich denke du wolltest array_merge()stattdessen?
Täuschung

4

Ich glaube, dies ist die sauberste Lösung, ohne Mutationen oder unbekannte Klassen zu verwenden.

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

Probieren Sie die folgende einfache Funktion aus:

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

Also daraus:

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

du erhältst:

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

Vielleicht sollten Sie Ihre Funktion überprüfen ... scheint keine Arbeit wie erwartet
Emiliano

@Emiliano Versuchen Sie, eine neue Frage zu stellen. Möglicherweise sind Ihre Eingabedaten anders, sodass dies in Ihrem speziellen Fall nicht funktioniert.
Kenorb

Wir haben nur wenige Probleme. Jedes ist eine veraltete Funktion. Sie können den Punkt verbessern, an dem Sie hier kein neuer Typ waren. Sie sollten es als zweites wissen, wenn Ihr Code mit einer bestimmten Version von PHP funktioniert. Sagen Sie es als drittes, wenn Sie nicht mit allen Daten arbeiten. Sagen Sie es
Emiliano

2

Der Trick besteht darin, sowohl das Quell- als auch das Zielarray als Referenz zu übergeben.

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

Kernausschnitt


Dies scheint nur zweidimensionale Arrays zu unterstützen.
Alix Axel

Du hast recht. Es macht keinen Sinn, es zu benutzen. Ich denke, die beste Lösung ist die Antwort von "too much php".
Arsham


2

Wenn Sie eine Rekursion wirklich nicht mögen ... versuchen Sie stattdessen zu verschieben :)

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

Hinweis: In dieser einfachen Version werden Array-Schlüssel nicht unterstützt.


Dies ist ein interessanter Ansatz. Im Gegensatz zu den anderen Lösungen wird das ursprüngliche Array ($ a) bearbeitet. Wenn Sie es durch ein ersetzen, ist es continueetwas schneller.
Pcarvalho

2

Wie wäre es mit einem rekursiven Generator? 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

Für 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;
}

Bitte fügen Sie dieser Nur-Code-Antwort eine Erklärung bei.
Mickmackusa

1

Diese Version kann tiefe, flache oder eine bestimmte Anzahl von Ebenen ausführen:

/**
 * @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;
}

Erklären Sie zukünftigen Forschern nicht nur , was dieses Snippet leisten kann , sondern auch, wie es funktioniert.
Mickmackusa

1

Weil der Code hier beängstigend aussieht. Hier ist eine Funktion, die auch ein mehrdimensionales Array in eine HTML-Form-kompatible Syntax konvertiert, die jedoch einfacher zu lesen ist.

/**
 * 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

Dies kann durch Verwendung erreicht werden 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);

Arbeitsbeispiel: - https://3v4l.org/FpIrG


0

Dies ist meine Lösung unter Verwendung einer Referenz:

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

Bitte geben Sie eine Erklärung an, wie Ihr Snippet funktioniert und warum es eine gute Idee ist. Nur-Code-Antworten sind bei StackOverflow von geringem Wert, da sie das OP und zukünftige Forscher schlecht ausbilden / befähigen. Denken Sie daran, wir sprechen niemals NUR mit dem OP. Alte Seiten werden zum Schließen neuer Seiten verwendet. Daher müssen Seiten informativ genug sein, um Probleme auch für zukünftige Fragesteller zu lösen.
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

Hier ist ein vereinfachter Ansatz:

$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

Jeder, der nach einer wirklich sauberen Lösung sucht; Hier ist eine 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) ) ; 

Druckt

 0 0 0 0 0 0 derp 0 0 0 0 0 0 0 0 0

0

Einfach eine andere Lösung posten)

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

    return $result;
}

0

Wenn Sie auch Ihre Schlüssel behalten möchten, ist das eine Lösung.

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

Leider werden nur endgültig verschachtelte Arrays ohne mittlere Schlüssel ausgegeben. Also für das folgende Beispiel:

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

Ausgabe ist:

Array
(
    [a] => apple
    [b] => banana
    [sour] => lemon
)

-1

Ich musste ein mehrdimensionales PHP-Array im HTML-Eingabeformat darstellen.

$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 Wie ist dieser Kommentar relativ? Falscher Beitrag ..?
Gajus

Nein. Ich dachte, es wäre ziemlich ähnlich zu dem, was Sie tun, und habe beschlossen, es zu teilen. Ich denke, der einzige Unterschied besteht darin, dass meine Darstellung auch gültiges PHP ist - der Form $var['a']['b']['c'][0] = 'a'; ....
Alix Axel

Ich brauchte absichtlich HTML-Ausgabe. Trotzdem danke fürs Teilen.
Gajus

1
Ich denke, dass dies die richtige Antwort auf die falsche Frage ist. Versuchen Sie bei der Beantwortung bitte, die gestellte Frage so zu beantworten, wie sie gestellt wird. Andernfalls können die Seiten vom Kernthema abweichen und zukünftige Forscher verwirren.
Mickmackusa

-1

Wenn Sie ein Array von Objekten haben und es mit einem Knoten reduzieren möchten, verwenden Sie einfach diese Funktion:

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.