PHPは1つの配列を別の配列に追加します(array_pushまたは+ではありません)


278

キーを比較せずに配列を別の配列に追加する方法は?

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

最後に、Array( [0]=>a [1]=>b [2]=>c [3]=>d ) 次のようになります。[]またはのようなものを使用array_pushすると、次のいずれかの結果になります。

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

これは何かをする必要がありますが、よりエレガントな方法で行います。

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

16
array_merge ($a, $b)少なくともPHP 5以降では、望みどおりの動作をするはずです。
tloach 2010年


6
あなたが投稿した出力のいずれも、あなたが必要とするものの例外array_merge();ではarray_merge();ないはずです:print_r(array_merge($a,$b)); // outputs => Array ( [0] => a [1] => b [2] => c [3] => d )
acm

2
「追加」という用語にまったく同意しません。追加とは、実際には、ある配列の項目が別の(宛先)配列の要素になり、すでにいくつかの要素があるため、宛先配列が変更されることを意味します。Mergeは両方の配列の新しい配列とCOPIES要素を割り当てますが、追加は実際には追加のメモリ割り当てなしで宛先配列要素を再利用することを意味します。
tishma 14

回答:


424

array_merge エレガントな方法です:

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

次のようなことをする:

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

+演算子は実際にはそれらをマージしないため、機能しません。それら$aがと同じキーを持っている場合$b、それは何もしません。


16
キーが数値ではなく文字列である場合は注意してください。ドキュメントから:入力配列に同じ文字列キーがある場合、そのキーの
新しい

または現代の使用スプラット @bstoney回答としてオペレータをstackoverflow.com/a/37065301/962634
バジル

76

PHP 5.6以降でこれを行う別の方法は、...トークンを使用することです。

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

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

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

これは、 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');

警告にもかかわらず:

  • 7.3より前のPHPバージョンでは、次の場合に致命的なエラーが発生します。 $bは、これが空の配列であるか、走査できない、たとえば配列でない
  • PHP 7.3では、を$b通過できない場合に警告が表示されます

そのような構文にはどの用語が使用されていますか?(例えば、JSでは、spreadオペレーターと呼ばれます)または、ドキュメントへのリンクを提供できますか?
バジル

3
@basilは...一般的splat operatorにphpで呼ばれます。
mickmackusa

以前の要素を上書きせずに配列をそれ自体に追加する簡単な方法を探すときに最も役立つ答え。
DanielBöttner19年

1
array_push空の配列でのエラーを防ぐphp 7.3以降の単一の引数を受け入れます。
vctls

実際、これは最もエレガントで効率的な方法です。感謝
ハッサンアリセーラム

33

使ってみませんか

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

これを使用したくないのは、正しい組み込みメソッドです。


OPはarray_merge()を「使用したくない」とどこに言っているのでしょうか?
KittenCodings 2017

3
@KittenCodings-質問の「編集履歴」を読んでください...元の質問にタイトルが付けられていましたPHP append one array to another (not array_merge or array_push)...その後PHP append one array to another (not array_merge or +)、現在のタイトルに変更する前に変更されました
Mark Ba​​ker

2
@MarkBakerすごい!SOに編集履歴があることを知りませんでした!それについて申し訳ありませんが、おかげで、これは大幅に変更され、モデレーターが人々の口に言葉を入れることをいくらか妨げています。以前はいくつかの質問が改ざんされ、コンテンツが削除/編集されてコメントが無効にされたように感じましたが、ほとんどの人はおそらく読んでいないと思います編集履歴、これからも間違いなく
KittenCodings

21

かなり古い投稿ですが、ある配列を別の配列に追加することについて何か追加したいと思います。

もし

  • 1つまたは両方の配列に連想キーがあります
  • 両方の配列のキーは関係ありません

次のような配列関数を使用できます。

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

array_mergeは数値キーをマージしないため、$ appendArrayのすべての値を追加します。foreachループの代わりにネイティブのphp関数を使用している間、多くの要素を持つ配列ではより高速になるはずです。

追加2019-12-13: PHP 7.4以降、配列スプレッド演算子の方法で配列を追加または追加する可能性があります:

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

以前と同様に、キーはこの新機能の問題になる可能性があります。

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

「致命的エラー:キャッチされないエラー:文字列キーで配列をアンパックできません」

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


1
これには、入力配列をそのままにしておくという利点もあります。
Jon Surrell、2016年

1
はい、同じキーにマージしないようにarray_valuesを抽出する場合に備えて、より安全です。
ガブリエルロドリゲス

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

出力:

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
)

参照ソースコード


12

大きな配列の場合は、array_mergeなしで連結することをお勧めします。これは、メモリのコピーを回避するためです。

$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

私にとってはこの方法は50倍高速でした。
luttkens

9

bstoneyとSnarkによる回答に続いて、さまざまな方法でいくつかのテストを行いました。

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

生成されるもの:

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

オリジナル:PHP 7の時点で、方法3はforeachループが機能する方法により、はるかに優れた代替手段であると思います反復される配列のコピーを作成するています。

方法3は質問の「array_pushではない」の基準に対する厳密な回答ではありませんが、1行であり、あらゆる点で最も高いパフォーマンスですが、構文がオプションになる前に質問されたと思います。

更新25/03/2020:変数がリセットされなかったために欠陥があったテストを更新しました。興味深いことに(または混乱を招くように)結果は、テスト1が最速で、最も遅い場所である0.008392から0.002717に変化したことを示しています。これはPHPのアップデートに限られます。これは、テストの欠陥による影響を受けなかったためです。

だから、サガは続きます、私はこれからarray_mergeを使い始めます!


2
各テストの前にarray1をリセットしていないため、各テストには前のテストよりも50,000多い項目があります。
Dakusan

何年にもわたって素晴らしいので、あなたは私にこれを最初に取り上げてくれました。ありがとうございます。まもなく再テストを行います:)
Jamie Robinson

5

PHP 7.4以降では、...演算子を使用できます。これは、Rubyを含む他の言語ではsplatオペレーターとしても知られています。

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

出力

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

Splatオペレーターは、array_mergeよりも優れたパフォーマンスを持つ必要があります。これは、splat演算子が言語構造であり、array_mergeが関数であるだけでなく、コンパイル時の最適化が定数配列に対して実行可能であるためです。

さらに、通常の要素はsplat演算子の前または後に追加できるため、配列のどこにでもsplat演算子構文を使用できます。

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

3

PHP7より前は、以下を使用できます。

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

array_splice()配列(第1引数)を参照して動作し、第2引数から始まる値と第3引数の数のリストの代わりに配列(第4引数)の値を置きます。2番目の引数をソース配列の最後に設定し、3番目をゼロに設定すると、4番目の引数の値が1番目の引数に追加されます


削除しないスプライシングマジックに従わない人には、いくつかの説明を含める必要があります。
mickmackusa

0

空の配列を既存の新しい値とマージする場合。最初に初期化する必要があります。

$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

その助けを願っています。


0

foreachループは、array_mergeよりも高速で既存の配列に値を追加するため、配列を別の配列の最後に追加する場合は、代わりにループを選択します。

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

この回答は、ページに新しい情報をもたらしません。パフォーマンスの比較は何年も前に投稿されました。
mickmackusa

-4

これはどう:

$appended = $a + $b;

1
私が言ったように、それはキーを比較し、結果は次のようになります:Array([0] => a [1] => b)
Danil K

1
あなたは必ずそれがキーを比較しますか?文書はこう述べています(強調は私のことです):「入力配列に同じ文字列キーがある場合、そのキーの新しい値は前のキーを上書きします。ただし、配列に数値キーが含まれている場合、新しい値は元のキーを上書きしません値が追加されます。あなたのキーは実際には'0' => 'a'...ではなく...ではありません0 => 'a'か?
Piskvorが

@Piskvorでは、キーの「0」と0の間に違いはありません。
Gordon

ゴードンの権利。(整数キーではなく数値キーに重点が置かれています
netcoder、2010年

1
@ゴードン:ああ、そうだね。それが、私が2つのことを同時に考えることで得られるものです。php.net/manual/en/language.operators.array.phpは、次のドキュメントですarray + array
Piskvorが建物を去った
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.