PHP hängt ein Array an ein anderes an (nicht array_push oder +)

278

Wie kann man ein Array an ein anderes anhängen, ohne die Schlüssel zu vergleichen?

$a = array( 'a', 'b' );
$b = array( 'c', 'd' );

Am Ende sollte es sein: Array( [0]=>a [1]=>b [2]=>c [3]=>d ) Wenn ich so etwas wie []oder verwende array_push, führt dies zu einem der folgenden Ergebnisse:

Array( [0]=>a [1]=>b [2]=>Array( [0]=>c [1]=>d ) )
//or
Array( [0]=>c [1]=>d )

Es sollte einfach etwas sein, dies zu tun, aber auf elegantere Weise:

foreach ( $b AS $var )
    $a[] = $var;
Danil K.
quelle
16
array_merge ($a, $b)sollte genau das tun, was Sie wollen, zumindest mit PHP 5+.
Tloach
1
(verwandt) + Operator für Array in PHP
Gordon
6
Keine der von Ihnen geposteten Ausgaben stammt von array_merge();der Ausgabe von array_merge();sollte genau das sein, was Sie benötigen:print_r(array_merge($a,$b)); // outputs => Array ( [0] => a [1] => b [2] => c [3] => d )
acm
2
Ich bin völlig anderer Meinung als der Begriff "Anhängen". Anhängen bedeutet wirklich, dass Elemente eines Arrays zu Elementen eines anderen (Ziel-) Arrays werden, das möglicherweise bereits einige Elemente enthält, wodurch das Zielarray geändert wird. Beim Zusammenführen werden ein neues Array und COPIES-Elemente beider Arrays zugewiesen, während beim Anhängen die Ziel-Array-Elemente ohne zusätzliche Speicherzuweisung wiederverwendet werden.
Tishma

Antworten:

424

array_merge ist der elegante Weg:

$a = array('a', 'b');
$b = array('c', 'd');
$merge = array_merge($a, $b); 
// $merge is now equals to array('a','b','c','d');

So etwas tun wie:

$merge = $a + $b;
// $merge now equals array('a','b')

Funktioniert nicht, da der +Bediener sie nicht zusammenführt. Wenn sie $adie gleichen Schlüssel wie haben $b, wird es nichts tun.

Netcoder
quelle
16
Seien Sie vorsichtig, wenn Ihre Schlüssel keine Zahlen, sondern Zeichenfolgen sind. Aus doc: Wenn die Eingabearrays dieselben Zeichenfolgenschlüssel haben, überschreibt der spätere Wert für diesen Schlüssel den vorherigen
Dusan Plavak
oder verwenden Sie den modernen Splat- Operator als @bstoney Antwort stackoverflow.com/a/37065301/962634
Basilikum
76

Eine andere Möglichkeit, dies in PHP 5.6+ zu tun, wäre die Verwendung des ...Tokens

$a = array('a', 'b');
$b = array('c', 'd');

array_push($a, ...$b);

// $a is now equals to array('a','b','c','d');

Dies funktioniert auch mit jedem Traversable

$a = array('a', 'b');
$b = new ArrayIterator(array('c', 'd'));

array_push($a, ...$b);

// $a is now equals to array('a','b','c','d');

Eine Warnung :

  • In PHP-Versionen vor 7.3 führt dies zu einem schwerwiegenden Fehler, wenn $bein leeres Array vorhanden oder nicht durchlaufbar ist, z. B. kein Array
  • In PHP 7.3 wird eine Warnung ausgegeben, wenn sie $bnicht durchlaufbar ist
bstoney
quelle
Welcher Begriff wird für eine solche Syntax verwendet? (ZB heißt es in JS Spread Operator) Oder können Sie einen Link zu Dokumenten bereitstellen?
Basilikum
3
@basil finden Sie ...allgemein als die splat operatorin PHP bezeichnet.
Mickmackusa
Die nützlichste Antwort, wenn Sie nach einer einfachen Möglichkeit suchen, ein Array an sich selbst anzuhängen, ohne vorherige Elemente zu überschreiben.
Daniel Böttner
1
array_pushakzeptiert ein einzelnes Argument seit PHP 7.3, das Fehler mit leeren Arrays verhindert.
vctls
Tatsächlich ist dies der eleganteste und effizienteste Weg. danke
Hassan Ali Salem
33

Warum nicht verwenden

$appended = array_merge($a,$b); 

Warum möchten Sie nicht diese korrekte, integrierte Methode verwenden?

Mark Baker
quelle
Wo sagt OP, dass er array_merge () nicht verwenden will ...?
KittenCodings
3
@KittenCodings - Lesen Sie den "Bearbeitungsverlauf" der Frage ... die ursprüngliche Frage hatte den Titel PHP append one array to another (not array_merge or array_push)... wurde anschließend geändert, PHP append one array to another (not array_merge or +)bevor der aktuelle Titel geändert wurde
Mark Baker
2
@ MarkBaker Wow! Ich wusste nicht, dass SO einen Bearbeitungsverlauf hat! Tut mir leid, und danke, das ändert sich sehr und hindert Moderatoren ein wenig daran, Wörter in den Mund der Leute zu stecken. Ich hatte zuvor das Gefühl, dass einige Fragen unkenntlich gemacht und ihre Kommentare durch entfernte / bearbeitete Inhalte ungültig gemacht wurden, obwohl ich mir vorstelle, dass die meisten Leute wahrscheinlich nicht lesen Die Bearbeitungshistorie werde ich sicher von nun an
KittenCodings
21

Es ist ein ziemlich alter Beitrag, aber ich möchte etwas zum Anhängen eines Arrays an ein anderes hinzufügen:

Wenn

  • Ein oder beide Arrays haben assoziative Schlüssel
  • Die Schlüssel beider Arrays spielen keine Rolle

Sie können Array-Funktionen wie folgt verwenden:

array_merge(array_values($array), array_values($appendArray));

array_merge führt keine numerischen Schlüssel zusammen, sodass alle Werte von $ appendArray angehängt werden. Bei Verwendung von nativen PHP-Funktionen anstelle einer foreach-Schleife sollte diese auf Arrays mit vielen Elementen schneller sein.

Ergänzung 2019-12-13: Seit PHP 7.4 besteht die Möglichkeit, Arrays auf die Weise des Array Spread Operator anzuhängen oder voranzustellen:

    $a = [3, 4];
    $b = [1, 2, ...$a];

Nach wie vor können Schlüssel ein Problem mit dieser neuen Funktion sein:

    $a = ['a' => 3, 'b' => 4];
    $b = ['c' => 1, 'a' => 2, ...$a];

"Schwerwiegender Fehler: Nicht erfasster Fehler: Array kann nicht mit Zeichenfolgenschlüsseln entpackt werden"

    $a = [3 => 3, 4 => 4];
    $b = [1 => 1, 4 => 2, ...$a];

Array (4) {[1] => int (1) [4] => int (2) [5] => int (3) [6] => int (4)}

    $a = [1 => 1, 2 => 2];
    $b = [...$a, 3 => 3, 1 => 4];

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

SenseException
quelle
1
Dies sollte auch den Vorteil haben, dass die Eingabearrays unberührt bleiben.
Jon Surrell
1
Ja, es ist sicherer, nur für den Fall, dass die array_values ​​extrahiert werden, damit Sie nicht in dieselben Schlüssel zusammengeführt werden.
Gabriel Rodriguez
15
<?php
// Example 1 [Merging associative arrays. When two or more arrays have same key
// then the last array key value overrides the others one]

$array1 = array("a" => "JAVA", "b" => "ASP");
$array2 = array("c" => "C", "b" => "PHP");
echo " <br> Example 1 Output: <br>";
print_r(array_merge($array1,$array2));

// Example 2 [When you want to merge arrays having integer keys and
//want to reset integer keys to start from 0 then use array_merge() function]

$array3 =array(5 => "CSS",6 => "CSS3");
$array4 =array(8 => "JAVASCRIPT",9 => "HTML");
echo " <br> Example 2 Output: <br>";
print_r(array_merge($array3,$array4));

// Example 3 [When you want to merge arrays having integer keys and
// want to retain integer keys as it is then use PLUS (+) operator to merge arrays]

$array5 =array(5 => "CSS",6 => "CSS3");
$array6 =array(8 => "JAVASCRIPT",9 => "HTML");
echo " <br> Example 3 Output: <br>";
print_r($array5+$array6);

// Example 4 [When single array pass to array_merge having integer keys
// then the array return by array_merge have integer keys starting from 0]

$array7 =array(3 => "CSS",4 => "CSS3");
echo " <br> Example 4 Output: <br>";
print_r(array_merge($array7));
?>

Ausgabe:

Example 1 Output:
Array
(
[a] => JAVA
[b] => PHP
[c] => C
)

Example 2 Output:
Array
(
[0] => CSS
[1] => CSS3
[2] => JAVASCRIPT
[3] => HTML
)

Example 3 Output:
Array
(
[5] => CSS
[6] => CSS3
[8] => JAVASCRIPT
[9] => HTML
)

Example 4 Output:
Array
(
[0] => CSS
[1] => CSS3
)

Referenzquellcode

Hassan Amir Khan
quelle
12

Bei großen Arrays ist es besser, ohne array_merge zu verketten, um eine Speicherkopie zu vermeiden.

$array1 = array_fill(0,50000,'aa');
$array2 = array_fill(0,100,'bb');

// Test 1 (array_merge)
$start = microtime(true);
$r1 = array_merge($array1, $array2);
echo sprintf("Test 1: %.06f\n", microtime(true) - $start);

// Test2 (avoid copy)
$start = microtime(true);
foreach ($array2 as $v) {
    $array1[] = $v;
}
echo sprintf("Test 2: %.06f\n", microtime(true) - $start);


// Test 1: 0.004963
// Test 2: 0.000038
Snark
quelle
Funktioniert wie ein Zauber, für mich war dieser Ansatz 50x schneller.
Luttkens
9

Nach den Antworten von bstoney und Snark habe ich einige Tests mit den verschiedenen Methoden durchgeführt:

// Test 1 (array_merge)
$array1 = $array2 = array_fill(0, 50000, 'aa');
$start = microtime(true);
$array1 = array_merge($array1, $array2);
echo sprintf("Test 1: %.06f\n", microtime(true) - $start);

// Test2 (foreach)
$array1 = $array2 = array_fill(0, 50000, 'aa');
$start = microtime(true);
foreach ($array2 as $v) {
    $array1[] = $v;
}
echo sprintf("Test 2: %.06f\n", microtime(true) - $start);

// Test 3 (... token)
// PHP 5.6+ and produces error if $array2 is empty
$array1 = $array2 = array_fill(0, 50000, 'aa');
$start = microtime(true);
array_push($array1, ...$array2);
echo sprintf("Test 3: %.06f\n", microtime(true) - $start);

Welches produziert:

Test 1: 0.002717 
Test 2: 0.006922 
Test 3: 0.004744

ORIGINAL: Ich glaube, ab PHP 7 ist Methode 3 eine wesentlich bessere Alternative, da foreach-Schleifen jetzt so funktionieren , dass eine Kopie des Arrays erstellt wird, über das iteriert wird.

Während Methode 3 nicht unbedingt eine Antwort auf die Kriterien von 'not array_push' in der Frage ist, ist sie eine Zeile und in jeder Hinsicht die leistungsstärkste, aber ich denke, die Frage wurde gestellt, bevor die ... Syntax eine Option war.

UPDATE 25/03/2020: Ich habe den Test aktualisiert, der fehlerhaft war, da die Variablen nicht zurückgesetzt wurden. Interessanterweise (oder verwirrend) zeigen die Ergebnisse nun, dass Test 1 der schnellste ist, wo er am langsamsten war, nachdem er von 0,008392 auf 0,002717 gestiegen ist! Dies kann nur auf PHP-Updates zurückzuführen sein, da dies nicht durch den Testfehler beeinflusst worden wäre.

Also, die Saga geht weiter, ich werde von nun an array_merge verwenden!

Jamie Robinson
quelle
2
Sie setzen Array1 nicht vor jedem Test zurück, sodass jeder Test 50.000 Elemente mehr enthält als der vorherige.
Dakusan
Erstaunlich nach so vielen Jahren, dass Sie die erste Person sind, die mich darauf aufmerksam macht. Danke, ich werde in Kürze einen erneuten Test durchführen :)
Jamie Robinson
5

Seit PHP 7.4 können Sie den Operator ... verwenden . Dies wird in anderen Sprachen, einschließlich Ruby, auch als Splat-Operator bezeichnet .

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
var_dump($fruits);

Ausgabe

array(5) {
    [0]=>
    string(6) "banana"
    [1]=>
    string(6) "orange"
    [2]=>
    string(5) "apple"
    [3]=>
    string(4) "pear"
    [4]=>
    string(10) "watermelon"
}

Der Splat-Operator sollte eine bessere Leistung als array_merge haben . Dies liegt nicht nur daran, dass der Splat-Operator eine Sprachstruktur ist, während array_merge eine Funktion ist, sondern auch daran, dass die Optimierung der Kompilierungszeit für konstante Arrays performant sein kann.

Darüber hinaus können wir die Syntax des Splat-Operators überall im Array verwenden, da normale Elemente vor oder nach dem Splat-Operator hinzugefügt werden können.

$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
$arr3 = [...$arr1, ...$arr2];
$arr4 = [...$arr1, ...$arr3, 7, 8, 9];
dtar
quelle
3

Vor PHP7 können Sie Folgendes verwenden:

array_splice($a, count($a), 0, $b);

array_splice()arbeitet mit Bezug auf Array (1. Argument) und setzt Array-Werte (4. Argument) anstelle der Liste der Werte, die mit dem 2. Argument und der Nummer des 3. Arguments beginnen. Wenn wir das 2. Argument als Ende des Quellarrays und das 3. als Null setzen, hängen wir die 4. Argumentwerte an das 1. Argument an

Tutanchamun
quelle
Sie sollten diejenigen erklären, die der nicht entfernenden Spleißmagie nicht folgen.
Mickmackusa
0

Wenn Sie ein leeres Array mit einem vorhandenen neuen Wert zusammenführen möchten. Sie müssen es zuerst initialisieren.

$products = array();
//just example
for($brand_id=1;$brand_id<=3;$brand_id++){
  array_merge($products,getByBrand($brand_id));
}
// it will create empty array
print_r($a);

//check if array of products is empty
for($brand_id=1;$brand_id<=3;$brand_id++){
  if(empty($products)){
    $products = getByBrand($brand_id);
  }else{
    array_merge($products,getByBrand($brand_id));
  }
}
// it will create array of products

Hoffe seine Hilfe.

Drosanda
quelle
0

foreach-Schleife ist schneller als array_merge, um Werte an ein vorhandenes Array anzuhängen. Wählen Sie stattdessen die Schleife, wenn Sie ein Array am Ende eines anderen hinzufügen möchten.

// Create an array of arrays
$chars = [];
for ($i = 0; $i < 15000; $i++) {
    $chars[] = array_fill(0, 10, 'a');
}

// test array_merge
$new = [];
$start = microtime(TRUE);
foreach ($chars as $splitArray) {
    $new = array_merge($new, $splitArray);
}
echo microtime(true) - $start; // => 14.61776 sec

// test foreach
$new = [];
$start = microtime(TRUE);
foreach ($chars as $splitArray) {
    foreach ($splitArray as $value) {
        $new[] = $value;
    }
}
echo microtime(true) - $start; // => 0.00900101 sec
// ==> 1600 times faster
E_D
quelle
Diese Antwort bringt keine neuen Informationen auf die Seite. Leistungsvergleiche wurden Jahre zuvor veröffentlicht.
Mickmackusa
-4

Wie wäre es damit:

$appended = $a + $b;
Piskvor verließ das Gebäude
quelle
1
Wie ich bereits sagte, werden die Schlüssel verglichen und folgende Ergebnisse erzielt: Array ([0] => a [1] => b)
Danil K
1
Sind Sie sicher , dass es Schlüssel vergleichen wird? In der Dokumentation (Hervorhebung von mir) heißt es: "Wenn die Eingabearrays dieselben Zeichenfolgenschlüssel haben, überschreibt der spätere Wert für diesen Schlüssel den vorherigen. Wenn die Arrays jedoch numerische Schlüssel enthalten, überschreibt der spätere Wert das Original nicht." Wert, wird aber angehängt. ". Sind Sie sicher, dass Ihre Schlüssel nicht wirklich '0' => 'a'... statt 0 => 'a'?
Piskvor verließ das Gebäude
@Piskvor gibt es keinen Unterschied zwischen '0' und 0 für Schlüssel.
Gordon
Gordon hat recht. Der Schwerpunkt liegt auf numerischen Schlüsseln (im Gegensatz zu ganzzahligen Schlüsseln ).
Netcoder
1
@ Gordon: Ah, du hast recht - das ist es, was ich bekomme, wenn ich an zwei Dinge gleichzeitig denke. php.net/manual/en/language.operators.array.php ist eine Dokumentation fürarray + array
Piskvor verließ das Gebäude