この記事は、JavaScriptの基本的なスキルに属します。 2つのJSアレイを組み合わせ/マージするさまざまな一般的な方法を学び、さまざまな方法の利点と短所を比較します。
特定のシナリオを見てみましょう。
コードコピーは次のとおりです。
var q = [5、5、1、9、9、6、4、5、8];
var b = ["tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"];
明らかに、配列qとbの単純なスプライシングの結果は次のとおりです。
コードコピーは次のとおりです。
[
5、5、1、9、9、6、4、5、8、
「ネクタイ」、「マオ」、「csdn」、「ren "、" fu "、" fei "
]
concat(..)メソッド
最も一般的な使用法は次のとおりです。
コードコピーは次のとおりです。
var c = q.concat(b);
Q; // [5,5,1,9,6,4,5,8]
b; // ["tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"];
c; // [5,5,1,9,9,6,4,5,8、 "Tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"]]
ご覧のとおり、Cは2つの配列の組み合わせを表す真新しい配列です。QとBですが、QとBは現在役に立たないですよね?
Qアレイに10,000個の要素があり、Bアレイには10,000個の要素がある場合?次に、アレイCには20,000個の要素があり、メモリの2倍を占めます。
「これは大丈夫!」と思うかもしれません。 QとBを無駄にするだけで、ゴミが収集されますよね?問題は解決されます!
コードコピーは次のとおりです。
q = b = null; // `Q`および` b`はごみ収集されるようになりました
ええと?配列が小さい場合、当然問題はありません。ただし、大きな配列または繰り返し処理が必要な場合、メモリは制限されており、最適化する必要があります。
ループ挿入
OK、配列#push()メソッドを使用して、配列のコンテンツを別のものに追加してみましょう。
コードコピーは次のとおりです。
//配列 `b`を` q`に挿入します
for(var i = 0; i <b.length; i ++){
Q.push(b [i]);
}
Q; // [5,5,1,9,9,6,4,5,8、 "Tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"]]
b = null;
これで、2つの元の配列の内容がq(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、 "Tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"]]
q = null;
実用的なヒント
悲しいことに、forループは素朴で維持が困難です。もっと良くできますか?
アレイ#を最初に削減しましょう:
コードコピーは次のとおりです。
// `b` to` q`:
Q = b.Reduce(function(coll、item){
coll.push(item);
collを返します。
}、q);
Q; // [5,5,1,9,9,6,4,5,8、 "Tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"]]
//または `q`に` b`に:
b = Q.Reduceright(function(coll、item){
coll.unshift(item);
collを返します。
}、b);
b; // [5,5,1,9,9,6,4,5,8、 "Tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"]]
配列#reduce()とarray#reduceright()は非常にハイエンドですが、少しかさばっており、ほとんどの人はそれを覚えていません。 JS仕様6の=>矢印関数(矢印関数)はコードの量を大幅に減らすことができますが、各配列要素への関数呼び出しが必要です。これも非常に悪い方法です。
では、次のコードはどうですか?
コードコピーは次のとおりです。
// `b` to` q`:
Q.push.apply(q、b);
Q; // [5,5,1,9,9,6,4,5,8、 "Tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"]]
//または `q`に` b`に:
B.Unshift.Apply(B、Q);
b; // [5,5,1,9,9,6,4,5,8、 "Tie"、 "mao"、 "csdn"、 "ren"、 "fu"、 "fei"]]
大きいですね!?特に、unshift()メソッドは、以前のように反対の順序を考慮する必要はありません。 ES6の拡張オペレーター(スプレッドオペレーター、プレフィックス)がより高度になります:A.Push(... b)またはB.Unshift(... a)
ただし、実際、この方法はまだ楽観的すぎます。どちらの場合も、2番目のパラメーターとしてAまたはBを適用するために()を適用するかどうか(最初のパラメーターは、適用方法、つまりコンテキスト、スコープで関数を呼び出すときにこの内部になります)、または...拡張演算子方法では、アレイは実際に関数の引数に分割されます。
最初の主要な問題は、アレイを関数スタックにコピーする必要があるため、メモリを2倍にして(もちろん、一時的です!)ことです。さらに、異なるJSエンジンには異なる実装アルゴリズムがあり、関数が渡すことができるパラメーターの数を制限する場合があります。
配列が100万の要素を追加する場合、プッシュ()またはunshift()呼び出しであろうと、関数スタックで許可されたサイズを確実に超えます。この方法は、数千の要素がある場合にのみ利用可能であるため、特定の範囲を超えることに制限する必要があります。
注:Splice()を試すこともできます。Push(..)/unshift(..)と同じ制限があることを間違いなく見つけることができます。
1つのオプションは、この方法を継続することですが、バッチ処理を使用することです。
コードコピーは次のとおりです。
関数combineinto(q、b){
var len = q.length;
for(var i = 0; i <len; i = i+5000){
// 5,000個のアイテムは一度に処理されます
B.Unshift.Apply(B、Q.Slice(I、I+5000));
}
}
待って、コードの読みやすさを妥協します(パフォーマンスも!)。あきらめる前にこの旅を終えてください。
要約します
配列#concat()は、2つ(またはそれ以上)の配列を組み合わせるための試行およびテストされた方法です。しかし、彼は既存のアレイを変更する代わりに新しい配列を作成します。
適応するには多くの方法がありますが、それらはすべて異なる利点と短所を持ち、実際の条件に従って選択する必要があります。
さまざまな利点/短所が上記にリストされており、おそらく最良の(リストされていないものを含む)方法は削減(..)とreduceright(..)です。
あなたが選んだものは何でも、あなたはそれを当たり前のこととするのではなく、あなたの組み合わせと戦略について批判的に考えるべきです。