PHP bir dizi diğerine ekler (array_push veya + değil)


278

Anahtarlarını karşılaştırmadan bir diziyi diğerine nasıl ekleyebilirim?

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

Sonunda şöyle olmalıdır: veya Array( [0]=>a [1]=>b [2]=>c [3]=>d ) gibi bir şey kullanırsanız , bu sonuçlardan birine neden olur:[]array_push

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

Bunu yapmak bir şey olmalı, ama daha zarif bir şekilde:

foreach ( $b AS $var )
    $a[] = $var;

16
array_merge ($a, $b)en azından PHP 5+ ile tam olarak istediğinizi yapmalısınız.
tloach


6
Gönderdiğiniz çıkışların hiçbiri array_merge();çıktısından array_merge();gelmemelidir: İhtiyacınız olan şey tam olarak olmamalıdır:print_r(array_merge($a,$b)); // outputs => Array ( [0] => a [1] => b [2] => c [3] => d )
acm

2
"Eklemek" terimine tamamen katılmıyorum. Ekle, bir dizideki öğelerin zaten bazı öğeleri olan başka bir (hedef) dizinin öğeleri haline gelmesi ve dolayısıyla hedef dizinin değiştirilmesi anlamına gelir. Birleştirme her iki dizinin yeni bir dizisini ve COPIES öğelerini ayırırken, ekleme aslında hedef dizi öğelerini fazladan bellek ayırması olmadan yeniden kullanmak anlamına gelir.
tishma

Yanıtlar:


424

array_merge zarif yolu:

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

Gibi bir şey yapmak:

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

Çalışmaz, çünkü +operatör aslında onları birleştirmez. Onlar ise $aaynı tuşa sahiptir $b, bu bir şey yapmaz.


16
Anahtarların bir sayı ama dizeleri doc itibaren değilse Sadece dikkatli olun: Giriş diziler aynı dize anahtarlarını varsa, o zaman bu anahtarın sonradan değer öncekinin yerine konur
Dusan Plavak

ya da modern kullanmak uyarısı @bstoney cevap olarak operatörü stackoverflow.com/a/37065301/962634
fesleğen

76

PHP 5.6 ve sonraki sürümlerinde bunu yapmanın başka bir yolu ...belirteci kullanmaktır

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

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

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

Bu aynı zamanda herhangi bir 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');

Yine de bir uyarı :

  • PHP'nin 7.3'ten önceki sürümlerinde bu, $bboş bir dizi veya geçilemiyorsa ölümcül bir hataya neden olur , örneğin bir dizi değil
  • eğer PHP 7.3 bir uyarı yükseltilecek $bçaprazlanabiliyorsa değil

Bu sözdizimi için hangi terim kullanılır? (Örn, JS'de yayma operatörü olarak adlandırılır) Veya dokümanlara bağlantı sağlayabilir misiniz?
fesleğen

3
@ basil ...yaygın splat operatorphp olarak anılır bulacaksınız .
mickmackusa

Önceki öğeleri geçersiz kılmadan kendi kendine bir dizi eklemenin basit bir yolunu ararken en yararlı cevap.
Daniel Böttner

1
array_pushphp 7.3'ten bu yana, boş dizilerdeki hataları önleyen tek bir argümanı kabul eder.
vctls

aslında, bu en zarif ve verimli yoldur. teşekkürler
Hassan Ali Salem

33

Neden kullanmıyorsun

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

Bunu neden doğru, yerleşik yöntemi kullanmak istemiyorsunuz?


OP, "kullanmak istemediğini" dizi_merge () ... nerede diyor?
KittenCodings

3
@KittenCodings - Sorunun "düzenleme geçmişini" okuyun ... orijinal soru haklıydı PHP append one array to another (not array_merge or array_push)... daha sonra PHP append one array to another (not array_merge or +)şu anki başlığına geçmeden önce değiştirildi
Mark Baker

2
@MarkBaker Wow! SO'nun düzenleme geçmişi olduğunu bilmiyordum! Bunun için üzgünüm ve teşekkürler, bu çok değişir ve moderatörlerin insanların ağızlarına kelime koymasını önler, daha önce bazı soruların tahrif edildiğini ve yorumlarının içerik tarafından geçersiz kılındığını / düzenlendiğini düşünmüştüm, ancak çoğu insanın muhtemelen okumadığını hayal ediyorum düzenleme geçmişi, eminim bundan sonra heck olacak
KittenCodings

21

Oldukça eski bir yazı, ama bir dizi diğerine ekleme hakkında bir şeyler eklemek istiyorum:

Eğer

  • dizilerin birinde veya her ikisinde ilişkilendirilebilir anahtarlar var
  • her iki dizinin de anahtarları önemli değil

dizi işlevlerini şu şekilde kullanabilirsiniz:

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

array_merge sayısal anahtarları birleştirmez, böylece $ appendArray öğesinin tüm değerlerini ekler. Bir foreach döngüsü yerine yerel php işlevlerini kullanırken, öğeleri çok olan dizilerde daha hızlı olmalıdır.

Ekleme 2019-12-13: PHP 7.4'ten beri, dizileri Array Spread Operator yoluna ekleme veya önleme olanağı vardır:

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

Daha önce olduğu gibi, tuşlar bu yeni özellikle ilgili bir sorun olabilir:

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

"Önemli hata: Yakalanmadı Hatası: Dizi, dize anahtarlarıyla açılamıyor"

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

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

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

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


1
Bunun, giriş dizilerini dokunulmadan bırakma avantajı da olmalıdır.
Jon Surrell

1
Evet, aynı anahtarlarla birleştirilmemeniz için dizi değerlerini ayıklamak daha güvenlidir.
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));
?>

Çıktı:

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
)

Referans Kaynak Kodu


12

Büyük bir dizi için, bir bellek kopyasını önlemek için array_merge olmadan bitiştirmek daha iyidir.

$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

Bir cazibe gibi çalışır, benim için bu yaklaşım 50 kat daha hızlıydı.
luttkens

9

Yanıtlayan bstoney ve Snark'ın ardından çeşitli yöntemler üzerinde bazı testler yaptım:

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

Hangi üretir:

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

ORİJİNAL: PHP 7'den itibaren, yöntem 3'ün foreach döngülerinin şimdi hareket etme biçimi nedeniyle çok daha iyi bir alternatif olduğuna inanıyorum , bu da yinelenen dizinin bir kopyasını yapmaktır.

Yöntem 3 kesinlikle 'dizi_push değil' ölçütlerine kesinlikle bir cevap olmasa da, bir satır ve her açıdan en yüksek performans olsa da, bence soru ... sözdizimi bir seçenek değildi.

UPDATE 25/03/2020: Değişkenler sıfırlanmadığı için hatalı olan testi güncelledim. İlginçtir (ya da kafa karıştırıcı) sonuçlar şimdi test 1'in en hızlı olduğunu, en yavaş olduğu yerde, 0.008392'den 0.002717'ye gittiğini gösteriyor! Bu sadece PHP güncellemelerine düşebilir, çünkü bu test hatasından etkilenmeyecektir.

Yani, destan devam ediyor, bundan sonra array_merge kullanmaya başlayacağım!


2
Her testten önce dizi1'i sıfırlamıyorsunuz, bu nedenle her testte bir öncekinden 50.000 öğe daha var.
Dakusan

Çok uzun yıllar sonra beni bu konuda ilk kişi, teşekkür ederim, kısa bir süre sonra tekrar test edeceğim :)
Jamie Robinson

5

PHP 7.4'ten beri ... işleci kullanabilirsiniz . Bu, Ruby dahil diğer dillerde uyarıcı operatörü olarak da bilinir .

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

Çıktı

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

Splat işleci , array_merge'den daha iyi performansa sahip olmalıdır . Bunun nedeni sadece splat operatörünün dizi_merge bir işlevken bir dil yapısı olması değil, aynı zamanda derleme zamanı optimizasyonunun sabit diziler için de performans gösterebilmesidir.

Ayrıca, splat operatörü sözdizimini dizinin her yerinde kullanabiliriz, çünkü splat operatörünün önüne veya arkasına normal elemanlar eklenebilir.

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

3

PHP7'den önce şunları kullanabilirsiniz:

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

array_splice()dizi (1. bağımsız değişken) referansı ile çalışır ve dizi (4. bağımsız değişken) değerlerini 2. bağımsız değişken ve 3. bağımsız değişken sayısından başlayan değerler listesi yerine koyar. Kaynak dizinin sonu olarak 2. bağımsız değişkeni ve 3. sıfırı sıfır olarak ayarladığımızda, 4. bağımsız değişkeni 1. bağımsız değişkene ekleriz


Çıkarmayan yapıştırma sihrini takip etmeyenlere bir açıklama eklemelisiniz.
mickmackusa

0

boş diziyi mevcut yeni değerle birleştirmek istiyorsanız. Önce başlatmalısınız.

$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

Yardımını umuyorum.


0

foreach döngüsü mevcut bir diziye değer eklemek için array_merge'den daha hızlıdır, bu nedenle başka bir dizinin sonuna dizi eklemek istiyorsanız bunun yerine döngüyü seçin.

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

Bu yanıt sayfaya yeni bilgi getirmez. Performans karşılaştırmaları yıllar önce yayınlanmıştır.
mickmackusa

-4

Buna ne dersin:

$appended = $a + $b;

1
Söylediğim gibi anahtarları karşılaştıracak ve aşağıdakilerle sonuçlanacaktır: Dizi ([0] => a [1] => b)
Danil K

1
Anahtarları karşılaştıracağından emin misiniz ? Dokümantasyon diyor (benimki vurgu): "Giriş dizileri aynı dize anahtarlarına sahipse, o anahtar için sonraki değer öncekinin üzerine yazılır. Ancak, diziler sayısal anahtarlar içeriyorsa, sonraki değer orijinalin üzerine yazmaz değerini ekleyin, ancak eklenecektir. " Anahtarlarınızın aslında değil '0' => 'a'... olduğundan emin misiniz 0 => 'a'?
Piskvor binadan

@Piskvor, anahtarlar için '0' ile 0 arasında fark yoktur.
Gordon

Gordon haklı. Vurgu sayısal tuşlar üzerindedir ( tamsayı tuşlarının aksine ).
netcoder

1
@ Gordon: Ah, haklısın - aynı anda iki şeyi düşünmek için aldığım şey bu. php.net/manual/en/language.operators.array.php için belgelerarray + array
Piskvor binadan ayrıldı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.