Wie flacht man ein mehrdimensionales Array ab?

Lesezeit: 8 Minuten

Wie flacht man ein mehrdimensionales Array ab
Alix Axel

Ist es in PHP möglich, ein (zwei-/mehr-)dimensionales Array ohne Verwendung von Rekursion oder Referenzen zu glätten?

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

  • Warum Rekursion vermeiden?

    – JorenB

    23. August 2009 um 23:53 Uhr

  • Dupe (meistens) stackoverflow.com/questions/526556/…

    – Kletus

    23. August 2009 um 23:53 Uhr

  • Sie können mit allen Elementen eines beliebig tiefen Arrays ohne Rekursion nichts anfangen (Sie können es als Iteration tarnen, aber Potato, Potahto.) Wenn Sie nur vermeiden möchten, den Code für die Rekursionsbehandlung selbst zu schreiben, verwenden Sie dk2.php.net/manual/en/function.array-walk-recursive.php mit einem Callback, der das Element zu einem verfügbaren Array hinzufügt (verwenden Sie global, den Parameter userdata, packen Sie alles in eine Klasse und verweisen Sie auf $this usw.)

    – Michael Madson

    24. August 2009 um 0:05 Uhr

  • @JorenB: Ich würde gerne sehen, dass eine Implementierung archiviert werden könnte.

    – Alix Axel

    24. August 2009 um 1:42 Uhr

  • Schau mal rein ebnen Funktion ab Nsp. Sie können damit auch eine Tiefe angeben.

    – Ihor Burlachenko

    24. Februar 2016 um 20:34 Uhr

Du kannst den … benutzen Standard-PHP-Bibliothek (SPL) um die Rekursion zu “verstecken”.

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

Drucke

1 2 3 4 5 6 7 8 9 

  • Bin ich der einzige, der ‘RecursiveIteratorIterator’ für einen dummen Namen hält?

    – Nilamo

    24. August 2009 um 6:51 Uhr

  • Es ist eher “logisch” als “eingängig”. Nicht alles kann einen fantastischen Namen haben wie JOGL, Knol oder Azure 🙂

    – VolkerK

    24. August 2009 um 8:35 Uhr

  • Dies funktioniert nicht für leere Arrays als Kinder. Sie werden als Elternteil zurückgegeben.

    – hakre

    22. Oktober 2011 um 15:30 Uhr

  • iterator_to_array($it, false) vermeidet die Notwendigkeit für das foreach.

    – Alix Axel

    20. Februar 2013 um 14:17 Uhr


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

    – Mike S.

    10. Januar 2014 um 20:25 Uhr


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

    – Otheus

    26. November 2019 um 14:05 Uhr

  • @Otheus Das liegt daran, dass die obige Lösung keine Rekursion verwendet. Wie Sie sagten, erfordert es ein Array von Arrays. Aber auf der positiven Seite sollte dies viel schneller sein als die anderen Methoden, da es nicht den zusätzlichen Overhead der Funktionsaufrufe hat.

    – Joyce Babu

    26. November 2019 um 15:30 Uhr

  • Gibt einen Fehler aus, wenn das äußere Array leer ist, könnte in Kombination mit einem leeren Array vermeidbar sein array_merge([], ...$a);

    – Mohamed Gharib

    1. Januar 2020 um 1:38 Uhr

  • Wow, das ist eine coole, verrückte Syntax. 5 Jahre PHP-Programmierung und noch nie von diesem (…) Operator gehört. Funktioniert aber wie ein Zauber!

    – Robert Sinclair

    29. Februar 2020 um 7:46 Uhr

  • sehr cool. nicht richtig für 100% der Situationen, aber perfekt, wenn es funktioniert. $a = array_merge( array(), ...array_values( $a ) ); Bei mir hat es funktioniert, die Ergebnisse der Abfrage mit einer einzigen Spalte in WordPress zu glätten $wpdb->get_results( $sql, ARRAY_N )

    – Kandiszucker

    23. Dezember 2020 um 20:59 Uhr

Wie flacht man ein mehrdimensionales Array ab
Prasanth Bendra

Lösung für zweidimensionales Array

Bitte versuchen Sie Folgendes:

$array  = your array

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

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

EDIT: 21. August 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 funktionierte an einem Array, das ich von PDO erhielt, wo die anderen Lösungen dies nicht taten.

    – JAL

    30. November 2013 um 23:04 Uhr


  • Das 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 raffinierte Lösung, wenn Sie sicher wissen, dass Ihr Array nicht leer sein wird, aber das ist keine gängige Annahme, die viele machen können.

    – Ziege

    15. Januar 2015 um 6:42 Uhr

  • Das OP hat ausdrücklich nach nicht rekursiven Lösungen gefragt.

    – Lux

    20. Juli 2017 um 20:27 Uhr

  • Wow, coole 2D-Flattern! Aber um dies zu verhindern, verwenden Sie es einfach $result = $array ?call_user_func_array('array_merge', $array) : [];

    – Alexander Goncharov

    4. März 2018 um 10:29 Uhr

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

    – FantomX1

    18. September 2018 um 11:44 Uhr

1647087249 128 Wie flacht man ein mehrdimensionales Array ab
Walf

Um ohne Rekursion zu glätten (wie Sie es gewünscht haben), können Sie a verwenden Stapel. Natürlich können Sie dies in eine eigene Funktion packen array_flatten. Das Folgende ist eine Version, die ohne Tasten 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
        {
            array_unshift($stack, ...$value);
        }
        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 möglich, auch Schlüssel zu berücksichtigen, aber Sie benötigen eine andere Strategie, um mit dem Stack umzugehen. Dies ist erforderlich, da Sie mit möglichen doppelten Schlüsseln in den Unterarrays umgehen müssen. Eine ähnliche Antwort in einer verwandten Frage: PHP Gehen Sie durch ein mehrdimensionales Array, während Sie Schlüssel beibehalten

Ich bin mir nicht ganz sicher, aber ich hatte das in der Vergangenheit getestet: The RecurisiveIterator verwendet Rekursion, also hängt es davon ab, was Sie wirklich brauchen. Es sollte möglich sein, auch einen rekursiven Iterator 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 basierend auf zu implementieren RecursiveIterator was ich für eine schöne idee halte.

  • Vielen Dank, der erste funktionierte an einem Array, das ich von PDO erhielt, wo die anderen Lösungen dies nicht taten.

    – JAL

    30. November 2013 um 23:04 Uhr


  • Das 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 raffinierte Lösung, wenn Sie sicher wissen, dass Ihr Array nicht leer sein wird, aber das ist keine gängige Annahme, die viele machen können.

    – Ziege

    15. Januar 2015 um 6:42 Uhr

  • Das OP hat ausdrücklich nach nicht rekursiven Lösungen gefragt.

    – Lux

    20. Juli 2017 um 20:27 Uhr

  • Wow, coole 2D-Flattern! Aber um dies zu verhindern, verwenden Sie es einfach $result = $array ?call_user_func_array('array_merge', $array) : [];

    – Alexander Goncharov

    4. März 2018 um 10:29 Uhr

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

    – FantomX1

    18. September 2018 um 11:44 Uhr

Ich dachte nur, ich würde darauf hinweisen, dass dies eine Faltung ist, sodass 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 Weise 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

    17. Juli 2013 um 17:29 Uhr

  • @atamur Dies funktioniert auf PHP 5.3+. Wie im Änderungsprotokoll für array_reduce erwähnt, konnte $initial vor 5.3 nur eine Ganzzahl sein, dann durfte es “gemischt” sein (dh alles, was Ihre Reduktionsfunktion unterstützt).

    – Warbo

    19. Juli 2013 um 13:20 Uhr

  • @AlixAxel Sie haben Recht, dass mehrdimensional! = zweidimensional, aber dies kann so zusammengesetzt werden, dass eine beliebige Anzahl von Ebenen abgeflacht wird. Eine nette Konsequenz des Komponierens von Falten ist, dass es einer festen Grenze gehorcht; Wenn ich ein Array auf 5 Ebenen verschachtelt habe, kann ich es fold es in 4 Ebenen, oder fold . fold es um 3 Ebenen zu bekommen, oder fold . fold . fold es um 2 Level zu bekommen usw. Dies verhindert auch, dass Bugs versteckt werden; z.B. Wenn ich ein 5D-Array glätten möchte, aber ein 4D-Array bekomme, wird der Fehler sofort ausgelöst.

    – Warbo

    19. Juli 2013 um 13:35 Uhr

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

    – Tom Auger

    12. März 2016 um 0:36 Uhr

  • Ich stimme zu, dass Ihre Definition auf einer Ebene die beste Antwort ist, sie ist auch wunderbar ordentlich. Ich denke jedoch, dass Sie es falsch benannt haben $concatich denke, du solltest es einfach anrufen $flatten. array_merge ist das PHP-Äquivalent von concat. Ich habe es versucht bekommen array_concat als Alias ​​für hinzugefügt array_merge.

    – icc97

    29. Oktober 2017 um 15:27 Uhr


993580cookie-checkWie flacht man ein mehrdimensionales Array ab?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy