هذه المقالة تنتمي إلى المهارات الأساسية لجافا سكريبت. سوف نتعلم العديد من الأساليب المشتركة لدمج/دمج صفيف اثنين من 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" ، "رن" ، "فو" ، "فاي"
]
concat (..) طريقة
الاستخدامات الأكثر شيوعا هي كما يلي:
نسخة الكود كما يلي:
var c = q.concat (b) ؛
س. // [5،5،1،9،6،4،5،8]
ب ؛ // ["Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"] ؛
ج. // [5،5،1،9،6،4،5،8 ، "Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"]
كما ترون ، C عبارة عن صفيف جديد يمثل مزيجًا من المصفوفتين: Q و B ، لكن Q و B عديمة الفائدة الآن ، أليس كذلك؟
إذا كان لدى صفيف Q 10000 عنصر ، و Barray لديها 10000 عنصر؟ ثم يحتوي الصفيف C الآن على 20.000 عنصر ، يحتل ضعف الذاكرة.
"هذا جيد!" ، قد تعتقد. فقط ضع Q و B عبثًا ، وبعد ذلك سيتم جمع القمامة ، أليس كذلك؟ تم حل المشكلة!
نسخة الكود كما يلي:
س = ب = فارغة ؛ // "Q` و" B` يمكن الآن جمع القمامة
أم؟ إذا كانت المصفوفات صغيرة ، فلا توجد مشكلة بشكل طبيعي. ومع ذلك ، عندما تكون المصفوفات الكبيرة أو المعالجة المتكررة مطلوبة ، تكون الذاكرة محدودة ، كما تحتاج إلى تحسينها.
إدراج حلقة
حسنًا ، لنحاول إضافة محتويات صفيف إلى آخر ، باستخدام طريقة Array#push ():
نسخة الكود كما يلي:
// إدراج صفيف `b` في` Q`
لـ (var i = 0 ؛ i <b.length ؛ i ++) {
q.push (b [i]) ؛
}
س. // [5،5،1،9،6،4،5،8 ، "Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"]
ب = خالية ؛
الآن ، يتم تخزين محتويات صفيفتين أصليتين في Q (Q + B).
يبدو أنه قام بعمل جيد في تحسين الذاكرة.
ولكن ماذا لو كانت صفيف Q صغيرة جدًا و B كبيرة جدًا؟ لاعتبارات الذاكرة والسرعة ، تريد إدخال Q الأصغر في مقدمة B. لا توجد مشكلة ، ما عليك سوى استخدام طريقة UNSHIFT () بدلاً من PUSH () ، ويجب إجراء اجتياز المقابل من كبير إلى صغير:
نسخة الكود كما يلي:
// `Q` في` b`:
لـ (var i = q.length-1 ؛ i> = 0 ؛ i--) {
B.Unshift (q [i]) ؛
}
ب ؛ // [5،5،1،9،6،4،5،8 ، "Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"]
س = خالية ؛
نصائح عملية
للأسف ، فإن حلقة من أجل ريفي ويصعب الحفاظ عليها. هل يمكننا أن نفعل ما هو أفضل؟
لنجرب Array#تقليل أولاً:
نسخة الكود كما يلي:
// `b` على` Q`:
q = b.reduce (function (coll ، item) {
coll.push (عنصر) ؛
إرجاع كول.
} ، س) ؛
س. // [5،5،1،9،6،4،5،8 ، "Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"]
// أو `Q` في` b`:
b = q.reduceright (function (coll ، item) {
coll.unshift (item) ؛
إرجاع كول.
} ، ب) ؛
ب ؛ // [5،5،1،9،6،4،5،8 ، "Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"]
Array#line () و array#reduceright () متطورة للغاية ، ولكنها ضخمة بعض الشيء ، ومعظم الناس لا يستطيعون تذكرها. يمكن أن تقلل وظائف السهم => (وظائف الأسهم) في مواصفات JS 6 بشكل كبير من كمية الكود ، ولكنها تتطلب مكالمات الوظائف لكل عنصر صفيف ، وهو أيضًا طريقة سيئة للغاية.
إذن ماذا عن الكود التالي؟
نسخة الكود كما يلي:
// `b` على` Q`:
q.push.apply (q ، b) ؛
س. // [5،5،1،9،6،4،5،8 ، "Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"]
// أو `Q` في` b`:
B.UNSHIFT.Apply (B ، Q) ؛
ب ؛ // [5،5،1،9،6،4،5،8 ، "Tie" ، "Mao" ، "CSDN" ، "Ren" ، "FU" ، "Fei"]
كبير أعلى ، صحيح!؟ على وجه الخصوص ، لا تحتاج طريقة UNSHIFT () إلى النظر في الترتيب المعاكس كما كان من قبل. عامل توسيع ES6 (مشغل الانتشار ، البادئة) أكثر تقدمًا: A.Push (... B) أو B.Unshift (... أ)
ومع ذلك ، في الواقع ، لا تزال هذه الطريقة متفائلة للغاية. في كلتا الحالتين ، سواء كان من الممكن تمرير A أو B لتطبيق () كمعلمة ثانية (تصبح المعلمة الأولى هذا داخليًا عند استدعاء الوظيفة في طريقة التطبيق ، أي السياق ، النطاق) ، أو طريقة عامل التوسع ، سيتم تقسيم الصفيف فعليًا إلى وسيطات الوظيفة.
المشكلة الرئيسية الأولى هي أنه يحتل ضعف الذاكرة (بالطبع ، مؤقت!) لأنه يجب نسخ الصفيف في مكدس الوظيفة. بالإضافة إلى ذلك ، تحتوي محركات JS المختلفة على خوارزميات تنفيذ مختلفة ، والتي قد تحد من عدد المعلمات التي يمكن أن تمر بها الوظيفة.
إذا أضاف صفيف مليون عنصر ، فسوف يتجاوز بالتأكيد الحجم المسموح به من قبل مكدس الوظائف ، سواء كان ذلك بمثابة مكالمة push () أو غير عملية (). هذه الطريقة متاحة فقط عندما يكون هناك بضعة آلاف عناصر ، لذلك يجب أن يقتصر على تجاوز نطاق معين.
ملاحظة: يمكنك أيضًا تجربة splice () ، وسوف تجد بالتأكيد أن لديها نفس القيد مثل Push (..)/unsonshift (..).
أحد الخيارات هو الاستمرار في استخدام هذه الطريقة ، ولكن مع معالجة الدُفعات:
نسخة الكود كما يلي:
دالة CombineInto (q ، b) {
var len = q.length ؛
لـ (var i = 0 ؛ i <len ؛ i = i+5000) {
// 5000 عنصر تتم معالجتها في وقت واحد
B.Unshift.apply (B ، Q.Slice (I ، I+5000)) ؛
}
}
انتظر ، نحن ننازل عن قابلية قراءة الكود (حتى الأداء!). إنهاء هذه الرحلة قبل أن نستسلم.
لخص
Array#Concat () هي طريقة مجربة ومختبرة للجمع بين صفيفتين (أو أكثر). لكنه ينشئ صفيفًا جديدًا بدلاً من تعديل الصفيف الموجود.
هناك العديد من الطرق للتكيف ، لكن لديهم جميعًا مزايا وعيوب مختلفة ويحتاجون إلى اختيارهم وفقًا للظروف الفعلية.
يتم سرد المزايا/العيوب المختلفة أعلاه ، وربما أفضل (بما في ذلك تلك غير المدرجة) هي تقليل (..) وخفض (..)
أيا كان ما تختاره ، يجب أن تفكر بشكل نقدي في مجموعة واستراتيجيتك بدلاً من أخذها كأمر مسلم به.