PHP menambahkan satu array ke array lain (bukan array_push atau +)

278

Bagaimana cara menambahkan satu array ke array lain tanpa membandingkan kunci mereka?

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

Pada akhirnya seharusnya: Array( [0]=>a [1]=>b [2]=>c [3]=>d ) Jika saya menggunakan sesuatu seperti []atau array_push, itu akan menyebabkan salah satu dari hasil ini:

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

Seharusnya sesuatu, melakukan ini, tetapi dengan cara yang lebih elegan:

foreach ( $b AS $var )
    $a[] = $var;
Danil K
sumber
16
array_merge ($a, $b)harus melakukan apa yang Anda inginkan, setidaknya dengan PHP 5+.
tloach
6
tidak ada output yang Anda posting berasal dari array_merge();output yang array_merge();harus tepat apa yang Anda butuhkan:print_r(array_merge($a,$b)); // outputs => Array ( [0] => a [1] => b [2] => c [3] => d )
ACM
2
Saya sangat tidak setuju dengan istilah "append". Append benar-benar berarti bahwa item dari satu array menjadi elemen dari array (tujuan) lain yang mungkin sudah memiliki beberapa elemen, oleh karena itu mengubah array tujuan. Gabungkan mengalokasikan elemen array dan COPIES baru dari kedua array, sedangkan append sebenarnya berarti menggunakan kembali elemen array tujuan tanpa alokasi memori tambahan.
tishma

Jawaban:

424

array_merge adalah cara yang elegan:

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

Melakukan sesuatu seperti:

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

Tidak akan bekerja, karena +operator sebenarnya tidak menggabungkannya. Jika mereka $amemiliki kunci yang sama $b, itu tidak akan melakukan apa pun.

netcoder
sumber
16
Berhati-hatilah jika kunci Anda bukan angka tetapi string, Dari doc: Jika array input memiliki kunci string yang sama, maka nilai nanti untuk kunci itu akan menimpa yang sebelumnya
Dusan Plavak
atau gunakan operator percikan modern sebagai @bstoney jawab stackoverflow.com/a/37065301/962634
basil
76

Cara lain untuk melakukan ini di PHP 5.6+ adalah dengan menggunakan ...token

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

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

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

Ini juga akan bekerja dengan siapa saja 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');

Sebuah peringatan meskipun:

  • dalam versi PHP sebelum 7.3 ini akan menyebabkan kesalahan fatal jika $barray kosong atau tidak dapat dilewati misalnya bukan array
  • dalam PHP 7.3 peringatan akan dimunculkan jika $btidak dapat dilalui
bstoney
sumber
Istilah mana yang digunakan untuk sintaksis seperti itu? (Misalnya di JS disebut operator sebaran) Atau dapatkah Anda memberikan tautan ke dokumen?
basil
3
@basil Anda akan menemukan yang ...biasa disebut sebagai splat operatordi php.
mickmackusa
Jawaban paling berguna ketika mencari cara sederhana untuk menambahkan array ke dirinya sendiri tanpa mengesampingkan elemen sebelumnya.
Daniel Böttner
1
array_pushmenerima argumen tunggal sejak php 7.3, yang mencegah kesalahan dengan array kosong.
vctls
sebenarnya, ini adalah cara yang paling elegan dan efisien. terima kasih
Hassan Ali Salem
33

Kenapa tidak digunakan

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

Mengapa Anda tidak ingin menggunakan ini, metode bawaan yang benar.

Mark Baker
sumber
Di mana OP mengatakan dia "tidak ingin menggunakan" array_merge () ...?
KittenCodings
3
@KittenCodings - Baca "sunting sejarah" dari pertanyaan ... pertanyaan asli berhak PHP append one array to another (not array_merge or array_push)... kemudian dimodifikasi PHP append one array to another (not array_merge or +)sebelum berubah ke judul saat ini
Mark Baker
2
@MarkBaker Wow! Saya tidak tahu SO memiliki riwayat edit! Maaf tentang itu, dan terima kasih, ini banyak berubah dan agak mencegah moderator dari memasukkan kata-kata ke mulut orang, saya sebelumnya merasa seperti beberapa pertanyaan dirusak dan komentar mereka dibatalkan oleh konten yang dihapus / diedit, meskipun saya membayangkan kebanyakan orang mungkin tidak membaca sunting riwayat, saya yakin akan mulai sekarang
KittenCodings
21

Itu posting yang cukup lama, tapi saya ingin menambahkan sesuatu tentang menambahkan satu array ke yang lain:

Jika

  • satu atau kedua array memiliki kunci asosiatif
  • kunci kedua array tidak masalah

Anda dapat menggunakan fungsi array seperti ini:

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

array_merge tidak menggabungkan kunci numerik sehingga menambahkan semua nilai $ appendArray. Saat menggunakan fungsi php asli alih-alih foreach-loop, seharusnya lebih cepat pada array dengan banyak elemen.

Tambahan 2019-12-13: Sejak PHP 7.4, ada kemungkinan untuk menambahkan atau menambahkan array dengan cara Array Spread Operator:

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

Seperti sebelumnya, kunci dapat menjadi masalah dengan fitur baru ini:

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

"Kesalahan fatal: Kesalahan Tidak Berhasil: Tidak dapat membuka array dengan kunci string"

    $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
sumber
1
Ini juga harus memiliki keuntungan membiarkan array input tidak tersentuh.
Jon Surrell
1
Ya itu lebih aman untuk berjaga-jaga jika mengekstrak array_values ​​sehingga Anda tidak bergabung ke kunci yang sama.
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));
?>

Keluaran:

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
)

Kode Sumber Referensi

Hassan Amir Khan
sumber
12

Untuk array besar, lebih baik untuk menggabungkan tanpa array_merge, untuk menghindari salinan memori.

$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
sumber
Bekerja seperti pesona, bagi saya pendekatan ini 50x lebih cepat.
luttkens
9

Sebagai lanjutan dari jawaban oleh bstoney dan Snark saya melakukan beberapa tes pada berbagai metode:

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

Yang menghasilkan:

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

ASLI: Saya percaya pada PHP 7, metode 3 adalah alternatif yang jauh lebih baik karena cara foreach loop sekarang bertindak , yaitu membuat salinan array yang diulang.

Sementara metode 3 tidak sepenuhnya merupakan jawaban untuk kriteria 'tidak array_push' dalam pertanyaan, itu adalah satu baris dan kinerja paling tinggi dalam semua hal, saya pikir pertanyaan itu ditanyakan sebelum ... sintaks adalah pilihan.

UPDATE 25/03/2020: Saya telah memperbarui tes yang cacat karena variabel tidak disetel ulang. Menariknya (atau membingungkan) hasilnya sekarang menunjukkan sebagai tes 1 sebagai yang tercepat, di mana itu paling lambat, setelah dari 0,008392 ke 0,002717! Ini hanya bisa turun ke pembaruan PHP, karena ini tidak akan terpengaruh oleh cacat pengujian.

Jadi, saga berlanjut, saya akan mulai menggunakan array_merge mulai sekarang!

Jamie Robinson
sumber
2
Anda tidak mengatur ulang array1 sebelum setiap tes, jadi setiap tes memiliki 50.000 item lebih banyak dari sebelumnya.
Dakusan
Luar biasa setelah bertahun-tahun Anda adalah orang pertama yang menjemput saya dalam hal ini, terima kasih, saya akan melakukan tes ulang segera :)
Jamie Robinson
5

Sejak PHP 7.4 Anda dapat menggunakan ... operator . Ini juga dikenal sebagai operator percikan dalam bahasa lain, termasuk Ruby.

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

Keluaran

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

Operator percikan harus memiliki kinerja yang lebih baik daripada array_merge . Itu tidak hanya karena operator percikan adalah struktur bahasa sementara array_merge adalah fungsi, tetapi juga karena kompilasi optimasi waktu dapat dilakukan untuk array konstan.

Selain itu, kita dapat menggunakan sintaks operator percikan di mana-mana dalam array, karena elemen normal dapat ditambahkan sebelum atau setelah operator percikan.

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

Sebelum PHP7 Anda dapat menggunakan:

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

array_splice()beroperasi dengan referensi ke array (argumen 1) dan menempatkan nilai array (argumen 4) di tempat daftar nilai dimulai dari argumen 2 dan jumlah argumen 3. Ketika kita menetapkan argumen ke-2 sebagai akhir dari array sumber dan ke-3 sebagai nol kita menambahkan nilai-nilai argumen ke-4 ke argumen ke-1

tutankhamun
sumber
Anda harus menyertakan beberapa penjelasan kepada mereka yang tidak mengikuti sihir penyambungan yang tidak menghapus.
mickmackusa
0

jika Anda ingin menggabungkan array kosong dengan nilai baru yang ada. Anda harus menginisialisasi terlebih dahulu.

$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

Semoga bantuannya.

Drosanda
sumber
0

foreach loop lebih cepat dari array_merge untuk menambahkan nilai ke array yang sudah ada, jadi pilih loop sebagai gantinya jika Anda ingin menambahkan array ke akhir yang lain.

// 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
sumber
Jawaban ini tidak membawa informasi baru ke halaman. Perbandingan kinerja telah diposting tahun sebelumnya.
mickmackusa
-4

Bagaimana dengan ini:

$appended = $a + $b;
Piskvor meninggalkan gedung
sumber
1
Ini akan membandingkan kunci, seperti yang saya katakan, dan menghasilkan dengan yang berikut: Array ([0] => a [1] => b)
Danil K
1
Apakah Anda yakin itu akan membandingkan kunci? Mengatakan dokumentasi (penekanan tambang): "Jika array input memiliki kunci string yang sama, maka nilai kemudian untuk kunci itu akan menimpa yang sebelumnya. Jika, bagaimanapun, array berisi kunci numerik, nilai kemudian tidak akan menimpa yang asli nilai, tetapi akan ditambahkan. " Apakah Anda yakin kunci Anda sebenarnya '0' => 'a'bukan ... bukan 0 => 'a'?
Piskvor meninggalkan gedung
@Piskvor tidak ada perbedaan antara '0' dan 0 untuk kunci.
Gordon
Gordon benar. Penekanannya adalah pada tombol numerik (bukan kunci integer ).
netcoder
1
@ Gordon: Ah, Anda benar - itulah yang saya dapatkan karena memikirkan dua hal sekaligus. php.net/manual/en/language.operators.array.php adalah dokumentasi untukarray + array
Piskvor meninggalkan gedung