LoginSignup
10
9

More than 5 years have passed since last update.

要素が増えるとarray_mergeが遅すぎたので角括弧構文で追加するべき【整数キー】【重複あり】

Last updated at Posted at 2015-10-21

結論

追記:コメント欄要参照
array_mergeは要素数が増えるほどパフォーマンスが低下する。
キーが重要でなく、重複整数をキーを変え追加したいならば1
角括弧構文$array[] = 値を使用すれば、パフォーマンスが低下しない

参考文献

配列結合演算子, array_merge, array_replace を徹底比較
お世話になっております。
すごく見やすいです。

やりたかったこと

preg_match_allの一致したキーワードを重複を認めつつ1次元配列に集めたい。
並び順、キーは重要でない。

preg_match_allの結果は第三引数の$array[0]内に、整数キーで格納される。
+では整数の重複が無視され、array_replaceでは上書きされてしまう。
重複整数でも追加されるのはarray_mergeだけだったので、array_mergeにしたところ、回数が増えるごとに極端に遅くなってしまった。

検証コード

array_merge

$start = microtime(true);
for ($i = 0, $all = array(); $i < 10000; ++$i) {
    //$rand = rand();
    $rand = '1234567890';
    $matches = array();
    preg_match_all('/123|456|789/', $rand, $matches);
    $before = microtime(true);
    $all = array_merge($all, $matches[0]);
    if (($i % 1000) == 0) {
        echo printf("%.12f", (microtime(true) - $before)) . PHP_EOL;
    }
}

//var_dump($all);
echo "End\n";
echo printf("%.12f", (microtime(true) - $start)) . PHP_EOL;
//diff用
file_put_contents('/tmp/merge',print_r($all, true));

push

$start = microtime(true);
for ($i = 0, $all = array(); $i < 10000; ++$i) {
    //$rand = rand();
    $rand = '1234567890';
    $matches = array();
    preg_match_all('/123|456|789/', $rand, $matches);
    $before = microtime(true);
    foreach($matches[0] as $value) {
        $all[] = $value;
    }
    if (($i % 1000) == 0) {
        echo printf("%.12f", (microtime(true) - $before)) . PHP_EOL;
    }
}

//var_dump($all);
echo "End\n";
echo printf("%.12f", (microtime(true) - $start)) . PHP_EOL;
//diff用
file_put_contents('/tmp/push',print_r($all, true));


結果


# php merge.php
0.00001382827814
0.00059795379614
0.00156402587914
0.00243592262314
0.00324916839614
0.00408887863214
0.00526213645914
0.00667285919214
0.00805711746214
0.00815606117214
End
48.14117693901115
# php push.php
0.00001621246314
0.00000190734914
0.00000095367414
0.00000095367414
0.00000214576714
0.00000095367414
0.00000095367414
0.00000119209314
0.00000095367414
0.00000309944214
End
0.05467796325714
# diff merge push -s
ファイルmergeとpushは同一


array_mergeが不利ないじわるな条件でしたが、
恐らくarray_mergeは添字振り直しで時間を食われている?
一方$array[] = 値では処理時間に配列数は関係ないように見える。
出力自体は一緒なので、値だけ欲しければ$array[] = 値が良さそう。


文字列キーが重複しないこと前提の場合、array_merge

foreeach($array as $key => $var) {
    $all[$key] = $var
}

どちらが早いかも気になる。


キーワードと出現回数をカウントアップしたら結果配列の結合は不要じゃないかな?
そっちの方が遅いかな?


  1. 重複整数を無視、上書きしないならば 

10
9
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9