บทความนี้เป็นทักษะพื้นฐานของ JavaScript เราจะเรียนรู้วิธีการทั่วไปที่หลากหลายในการรวม/รวมอาร์เรย์ 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,
"tie", "mao", "csdn", "ren", "fu", "fei"
-
concat (.. ) วิธีการ
ประเพณีที่พบบ่อยที่สุดมีดังนี้:
การคัดลอกรหัสมีดังนี้:
var c = q.concat (b);
ถาม; // [5,5,1,9,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 เป็นอาร์เรย์ใหม่เอี่ยมที่แสดงถึงการรวมกันของสองอาร์เรย์: Q และ B แต่ Q และ B ตอนนี้ไร้ประโยชน์ใช่ไหม?
หากอาร์เรย์ Q มี 10,000 องค์ประกอบและอาร์เรย์ B มี 10,000 องค์ประกอบ? จากนั้นอาร์เรย์ C ตอนนี้มีองค์ประกอบ 20,000 รายการซึ่งครอบครองหน่วยความจำสองเท่า
"นี่ก็โอเค!" คุณอาจคิดว่า เพียงแค่ใส่ Q และ B อย่างไร้ประโยชน์จากนั้นมันจะถูกเก็บรวบรวมขยะใช่ไหม? ปัญหาได้รับการแก้ไขแล้ว!
การคัดลอกรหัสมีดังนี้:
q = b = null; // `q` และ` b` สามารถรวบรวมขยะได้
อืม? หากอาร์เรย์มีขนาดเล็กแสดงว่าไม่มีปัญหา อย่างไรก็ตามเมื่อจำเป็นต้องมีอาร์เรย์ขนาดใหญ่หรือการประมวลผลซ้ำหน่วยความจำมี จำกัด และจำเป็นต้องได้รับการปรับให้เหมาะสม
การแทรกลูป
โอเคลองเพิ่มเนื้อหาของอาร์เรย์ไปยังอื่นโดยใช้เมธอดอาร์เรย์#push ():
การคัดลอกรหัสมีดังนี้:
// แทรกอาร์เรย์ `b` ลงใน` q`
สำหรับ (var i = 0; i <b.length; i ++) {
Q.Push (B [i]);
-
ถาม; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
b = null;
ตอนนี้เนื้อหาของสองอาร์เรย์ดั้งเดิมจะถูกเก็บไว้ใน Q (Q + B)
ดูเหมือนว่าจะทำงานได้ดีในการเพิ่มประสิทธิภาพหน่วยความจำ
แต่ถ้าอาร์เรย์ Q มีขนาดเล็กมากและ B มีขนาดใหญ่มาก? สำหรับการพิจารณาหน่วยความจำและความเร็วคุณต้องการแทรก Q ขนาดเล็กลงด้านหน้าของ B ไม่มีปัญหาเพียงแค่ใช้วิธี Unshift () แทนการกด () และการสำรวจที่สอดคล้องกันจะต้องดำเนินการจากขนาดใหญ่ถึงขนาดเล็ก:
การคัดลอกรหัสมีดังนี้:
// `q` เข้าไปใน` b`:
สำหรับ (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;
เคล็ดลับการปฏิบัติ
น่าเศร้าสำหรับการวนรอบนั้นเรียบง่ายและยากต่อการบำรุงรักษา เราทำได้ดีกว่านี้ไหม
ลองอาร์เรย์#ลดก่อน:
การคัดลอกรหัสมีดังนี้:
// `b` ไปที่` q`:
Q = B.Reduce (ฟังก์ชั่น (coll, item) {
coll.push (รายการ);
กลับมาคอล;
}, q);
ถาม; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
// หรือ `q` เข้าไปใน` b`:
b = q.reduceright (ฟังก์ชั่น (coll, item) {
coll.unshift (รายการ);
กลับมาคอล;
}, b);
B; // [5,5,1,9,9,6,4,5,8, "tie", "mao", "csdn", "ren", "fu", "fei"]
อาร์เรย์#ลด () และอาร์เรย์#reduceright () เป็นระดับสูงมาก แต่ค่อนข้างใหญ่และคนส่วนใหญ่จำไม่ได้ ฟังก์ชั่น => ลูกศร (ลูกศรฟังก์ชั่น) ในข้อกำหนด JS 6 สามารถลดจำนวนรหัสได้อย่างมาก แต่ต้องใช้ฟังก์ชั่นการเรียกใช้องค์ประกอบอาเรย์แต่ละอันซึ่งเป็นวิธีที่แย่มาก
แล้วรหัสต่อไปนี้ล่ะ?
การคัดลอกรหัสมีดังนี้:
// `b` ไปที่` q`:
q.push.apply (q, b);
ถาม; // [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)
อย่างไรก็ตามในความเป็นจริงวิธีนี้ยังคงมองโลกในแง่ดีเกินไป ในทั้งสองกรณีไม่ว่าจะเป็นการผ่าน A หรือ B เพื่อใช้ () เป็นพารามิเตอร์ที่สอง (พารามิเตอร์แรกกลายเป็นภายในนี้เมื่อฟังก์ชั่นการโทรในวิธีการใช้นั่นคือบริบทขอบเขต) หรือ ... วิธีการขยายตัวของผู้ดำเนินการ
ปัญหาที่สำคัญครั้งแรกคือมันใช้หน่วยความจำสองเท่า (แน่นอนชั่วคราว!) เพราะอาเรย์จำเป็นต้องคัดลอกไปยังสแต็กฟังก์ชั่น นอกจากนี้เครื่องยนต์ JS ที่แตกต่างกันมีอัลกอริทึมการใช้งานที่แตกต่างกันซึ่งอาจ จำกัด จำนวนพารามิเตอร์ที่ฟังก์ชันสามารถผ่านได้
หากอาร์เรย์เพิ่มองค์ประกอบหนึ่งล้านรายการมันจะเกินขนาดที่ได้รับอนุญาตจากฟังก์ชันสแต็กไม่ว่าจะเป็นการกด () หรือการโทรแบบไม่เปลี่ยน () วิธีนี้จะใช้ได้เฉพาะเมื่อมีองค์ประกอบสองสามพันดังนั้นจึงต้อง จำกัด ให้เกินช่วงที่กำหนด
หมายเหตุ: คุณสามารถลอง Splice () และคุณจะพบว่ามันมีข้อ จำกัด เช่นเดียวกับ push (.. )/unshift (.. )
ตัวเลือกหนึ่งคือการใช้วิธีนี้ต่อไป แต่ด้วยการประมวลผลแบบแบตช์:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น compineInto (q, b) {
var len = q.length;
สำหรับ (var i = 0; i <len; i = i+5000) {
// 5,000 รายการจะถูกประมวลผลในแต่ละครั้ง
b.unshift.apply (b, q.slice (i, i+5000));
-
-
เดี๋ยวก่อนเราประนีประนอมความสามารถในการอ่านรหัส (แม้กระทั่งประสิทธิภาพ!) สิ้นสุดการเดินทางครั้งนี้ก่อนที่เราจะยอมแพ้
สรุป
Array#concat () เป็นวิธีการทดลองและทดสอบสำหรับการรวมอาร์เรย์สอง (หรือมากกว่า) แต่เขาสร้างอาร์เรย์ใหม่แทนที่จะแก้ไขอันที่มีอยู่
มีหลายวิธีในการปรับตัว แต่พวกเขาทั้งหมดมีข้อดีและข้อเสียที่แตกต่างกันและจำเป็นต้องเลือกตามเงื่อนไขจริง
ข้อดี/ข้อเสียต่าง ๆ มีการระบุไว้ด้านบนและอาจเป็นวิธีที่ดีที่สุด (รวมถึงวิธีการที่ไม่ได้ระบุไว้) คือการลด (.. ) และลดระดับ (.. )
ไม่ว่าคุณจะเลือกอะไรคุณควรคิดอย่างมีวิจารณญาณเกี่ยวกับการผสมผสานและกลยุทธ์ของคุณแทนที่จะใช้เพื่อรับ