JSで配列を結合するいくつかの方法とメリット・デメリットの比較_基礎知識

WBOY
リリース: 2016-05-16 16:35:59
オリジナル
1407 人が閲覧しました

この記事は JavaScript の基本スキルに属し、2 つの JS 配列を結合/マージするさまざまな一般的な方法を学び、さまざまな方法の長所と短所を比較します。

最初に具体的なシナリオを見てみましょう:

コードをコピーします コードは次のとおりです:

var q = [5, 5, 1, 9, 9, 6, 4, 5, 8];
var b = [ "ネクタイ"、"マオ"、"csdn"、"レン"、"フ"、"フェイ" ];

明らかに、配列 q と b を単純に連結した結果は次のようになります:

コードをコピー コードは次のとおりです:

[
5、5、1、9、9、6、4、5、8、
「ネクタイ」、「マオ」、「csdn」、「レン」、「フ」、「フェイ」
]

concat(..) メソッド

最も一般的な使用法は次のとおりです:

コードをコピー コードは次のとおりです:

var c = q.concat( b );

q; // [5,5,1,9,9,6,4,5,8]
b; // ["ネクタイ","マオ","csdn","レン","フ","フェイ"];

c; // [5,5,1,9,9,6,4,5,8,"ネクタイ","マオ","csdn","レン","フ","フェイ"]

ご覧のとおり、c は新しい配列で、2 つの配列 q と b の組み合わせを表しますが、q と b はもう役に立ちませんよね?

q 配列に 10,000 個の要素があり、b 配列にも 10,000 個の要素がある場合、配列 c には 20,000 個の要素があり、このメソッドは 2 倍のメモリを消費します。

「そんなことは問題ない!」と思うかもしれません。q と b を空のままにすれば、問題は解決されます。

コードをコピー コードは次のとおりです:
q = b = null; // `q` と `b` はガベージ コレクションされるようになりました

配列が小さい場合は問題ありませんが、配列が大きい場合、または複数回の繰り返し処理が必要な場合は、メモリが制限されるため、最適化する必要があります。

ループ挿入

OK、Array#push() メソッドを使用して、ある配列の内容を別の配列に追加してみましょう:


// 配列 `b` を `q` に挿入します
for (var i=0; i q.push( b[i] );
}

q; // [5,5,1,9,9,6,4,5,8,"ネクタイ","マオ","csdn","レン","フ","フェイ"]

b = null;


ここで、q は 2 つの元の配列 (q b) の内容を格納します。

メモリの最適化がうまく行われているようです。

しかし、q 配列が小さく、b が大きい場合はどうなるでしょうか? メモリと速度の都合上、小さい方の q を b の前に挿入する必要があります。問題はありません。push( の代わりに unshift() メソッドを使用するだけです。 ) 以上です。対応するサイクルを大から小までたどる必要があります。


// `q` を `b` に変換します:
for (var i=q.length-1; i >= 0; i--) {
b.unshift( q[i] );
}

b; // [5,5,1,9,9,6,4,5,8,"ネクタイ","マオ","csdn","レン","フ","フェイ"]

q = null;


実践的なヒント

残念ながら、for ループは退屈で保守が困難です。もっと改善できないでしょうか?

まず Array#reduce を試してみましょう:



// `b` を `q` に置き換えます:
q = b.reduce( function(coll,item){
coll.push(アイテム);
リターンコール;
}, q );

q; // [5,5,1,9,9,6,4,5,8,"ネクタイ","マオ","csdn","レン","フ","フェイ"]

// または `q` を `b` に変換します:

b = q.reduceRight( function(coll,item){

coll.unshift(item);
リターンコール;
}, b );

b; // [5,5,1,9,9,6,4,5,8,"ネクタイ","マオ","csdn","レン","フ","フェイ"]

Array#reduce() と Array#reduceRight() は非常に派手ですが、少し面倒で、ほとんどの人は覚えられません。JS 仕様 6 の => アロー関数を使用すると、コードの量を大幅に削減できます。ただし、配列要素ごとに関数を呼び出す必要があり、これも非常に貧弱な方法です
。 では、以下のコードはどうでしょうか?

コードをコピー コードは次のとおりです:

// `b` を `q` に置き換えます:
q.push.apply( q, b );

q; // [5,5,1,9,9,6,4,5,8,"ネクタイ","マオ","csdn","レン","フ","フェイ"]

// または `q` を `b` に変換します:
b.unshift.apply( b, q );

b; // [5,5,1,9,9,6,4,5,8,"ネクタイ","マオ","csdn","レン","フ","フェイ"]

BIG のほうが高いですよね!? 特に unshift() メソッドは、以前のように逆の順序を考慮する必要はありません。 ..b ) または b.unshift( ...a )

しかし、実際には、このメソッドはまだ楽観的すぎます。どちらの場合も、a または b が 2 番目のパラメータとして apply() に渡されるかどうか (最初のパラメータは、適用モードで Function を呼び出すときに内部的に渡されます) になります。コンテキスト、スコープ)、または展開演算子を使用します。実際、配列は関数の引数に分割されます。
最初の大きな問題は、配列を関数スタックにコピーする必要があるため、メモリが 2 倍必要になることです。また、JS エンジンごとに実装アルゴリズムが異なるため、パラメータの数が制限される可能性があります。関数に渡すことができます。

配列に 100 万個の要素が追加されると、push() または unshift() の呼び出しに関係なく、関数スタックで許可されるサイズを確実に超えます。このメソッドは、要素が数千個ある場合にのみ使用できます。制限する必要があります。一定の範囲を超えることはできません。

注: splice() を試すこともできますが、push(..)/unshift(..) と同じ制限があることがわかります。

1 つのオプションは、この方法をバッチで使用し続けることです:

コードをコピー コードは次のとおりです:

関数combineInto(q,b) {
var len = q.length;
for (var i=0; i // 一度に 5000 個のアイテムを処理します
b.unshift.apply( b, q.slice( i, i 5000 ) );
}
}

待ってください、コードの読みやすさ (さらにはパフォーマンス) も損なわれています。諦める前にこの旅を終わらせましょう。

概要

Array#concat() は、2 つ (またはそれ以上) の配列を結合するための実証済みのメソッドですが、既存の配列を変更するのではなく、新しい配列を作成します。

代替方法は多数ありますが、それぞれに異なる長所と短所があり、実際の状況に応じて選択する必要があります。

上記にはさまざまな利点/欠点がリストされていますが、おそらく (リストされていないものも含めて) 最も優れているのは、reduce(..) とreduceRight(..) です

何を選択する場合でも、配列のマージ戦略について批判的に検討し、それを当然のことと考えないでください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート