“Javascript array 結合”とかで検索すると、concatを使う方法とスプレッド構文を使う方法が出てくるかと思います。
// concat
arr1 = arr1.concat(arr2);
// スプレッド構文
arr1 = [...arr1, ...arr2];
私も検索結果から適当にconcatを使っていたのですが、実際にどちらを使うべきなのかが少し気になりだしました。
そこで、「とりあえず速い方でいっか!」と安直に考え、concatとスプレッド構文の性能測定をすることにしました。
あとネタ枠でfor文でゴリゴリ結合する方法も測定しました。
測定結果
※測定は全て5回測定の平均値、単位はミリ秒。
結合する配列の要素数による性能比較
配列の要素数 | concat [ms] | スプレッド構文 [ms] | for文 [ms] |
1000 | 0 | 0.26 | 0.14 |
10,000 | 0.06 | 1.1 | 1.42 |
100,000 | 0.3 | 11.58 | 5.58 |
1,000,000 | 15.94 | 82.4 | 33.9 |
10,000,000 | 62.94 | 2,108.6 (=2秒) | 363.22 |
→大きい配列を結合する場合はconcat一択ですね。
(1000以下だと差は殆どなかったので滅茶苦茶呼び出すとかでなければどれ使っても影響なさそう)
結合する配列の数による性能比較
結合する配列の数 | concat [ms] | スプレッド構文 [ms] | for文 [ms] |
10 | 0.04 | 0.46 | 0.08 |
100 | 0.42 | 24.22 | 1.14 |
1,000 | 77.66 | 2,138.98 (=2sec) | 2.84 |
10,000 | 10,655.82 (=10sec) | 測定不可 | 18.16 |
→数が少ない内はconcat・数が多くなればfor文で自前実装、が性能的には良さそうです。
(参考:今回(要素数100)の場合は配列数120前後で性能が逆転)
結論
「でかい配列・大量の配列の結合は遅いに決まってるやろ!!」
とかいう大前提は置いておいて、どうしても結合が必要な場合は、以下のような使い分けになりそうです。
- 常識的な範囲で結合する場合
→どれ使っても大して影響ないと思うけど強いていうならconcat - 大きい配列を結合する場合
→concat一択 - 大量(100~1000以上)の配列を結合する場合
→for文で自前実装する(コードは後述)
コードの書き方であったり、環境によって結果は変わってくるとは思いますが(特に大量の配列結合する方)、arrayの結合に何を使うかの参考程度にはなるんじゃないかと思います。
以上です。
最後に測定コード載せておきます。
測定に使用したコード
<html>
<body>
<script type='text/javascript'>
// ここの値を変えて測定
const MERGED_ARRAY_NUM = 2;
const INNER_ARRAY_SIZE = 100;
console.log('elapsedTime1[ms],elapsedTime2[ms],elapsedTime3');
for(let i = 0; i < 5; i++) {
measurement();
}
function initArray() {
let array1 = new Array();
for (let i = 0; i < MERGED_ARRAY_NUM; i++) {
let array2 = new Array();
for (let j = 0; j < INNER_ARRAY_SIZE; j++) {
array2.push(String(i) + String(j));
}
array1.push(array2)
}
return array1;
}
function measurement() {
// 結合元
let array1 = initArray();
let array2 = initArray();
let array3 = initArray();
// 結合先
let mergedArray1 = new Array();
let mergedArray2 = new Array();
let mergedArray3 = new Array();
// 測定#1 concatで結合
let startTime1 = performance.now();
for (let i = 0; i < MERGED_ARRAY_NUM; i++) {
mergedArray1 = mergedArray1.concat(array1[i]);
}
let elapsedTime1 = performance.now() - startTime1;
// 測定#2 スプレッド構文で結合
let startTime2 = performance.now();
for (let i = 0; i < MERGED_ARRAY_NUM; i++) {
mergedArray2 = [...mergedArray2, ...array2[i]];
}
let elapsedTime2 = performance.now() - startTime2;
// 測定#3 for文使って自前で結合
let startTime3 = performance.now();
for (let i = 0; i < MERGED_ARRAY_NUM; i++) {
for (let j = 0; j < INNER_ARRAY_SIZE; j++) {
mergedArray3.push(array3[i][j]);
}
}
let elapsedTime3 = performance.now() - startTime3;
console.log(`${elapsedTime1},${elapsedTime2},${elapsedTime3}`);
}
</script>
<body>
</html>
参考
https://maku77.github.io/js/array/concat.html
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax
コメント