each_cons() - Ruby
เมธอด each_cons() ของ enumerable เป็นเมธอดในตัวของ Ruby ที่วนซ้ำสำหรับ N องค์ประกอบติดต่อกัน เริ่มจากแต่ละองค์ประกอบทุกครั้ง ถ้าไม่ให้บล็อก มันคืนค่า enumerator
JS เทียบเท่า each_cons()
สมมติว่าเรามีอาร์เรย์ตัวเลข (JS เทียบเท่า Ruby's enumerable ในกรณีนี้) ฟังก์ชัน each_cons ควรเป็นฟังก์ชันอาร์เรย์ที่ execute สำหรับแต่ละองค์ประกอบของอาร์เรย์ และรับตัวเลข N (N <= ความยาวอาร์เรย์) เป็นอาร์กิวเมนต์เดียว และคืนค่าอาร์เรย์ที่มี subarray ขนาด N โดยแต่ละ subarray เริ่มจากองค์ประกอบทีละตัว
ตัวอย่างจะทำให้ชัดเจนขึ้น
สมมติว่าเรามีอาร์เรย์แบบนี้ −
const arr = [1, 2, 3, 4, 5]; console.log(arr.eachCons(2));
การเรียก eachCons นี้ทำอะไรคือ สร้างอาร์เรย์ของอาร์เรย์ที่มี 2 องค์ประกอบแต่ละอันแบบนี้ −
[[1, 2], [2, 3], [3, 4], [4, 5]]
สังเกตว่า subarray ถูกสร้างสำหรับแต่ละองค์ประกอบของอาร์เรย์ต้นฉบับจนกว่าเราจะทำไม่ได้
ถ้าค่า N เป็น 3 แทน 2 ผลลัพธ์จะเป็น −
[[1, 2, 3], [2, 3, 4], [3, 4, 5]]
อีกครั้ง subarray ถูกสร้างสำหรับทุกองค์ประกอบของอาร์เรย์จนกว่าเราจะมีองค์ประกอบพอในอาร์เรย์
วิธีการ
เราจะใช้ sliding window algorithm เพื่อแก้ปัญหานี้
แม้เราจะใช้ฟังก์ชัน ES6 สมัยใหม่แก้ได้ในสองบรรทัด แต่วิธีก่อนหน้ามีประสิทธิภาพมากกว่า
ขั้นแรก เราจะใช้ while loop ที่สร้าง initial window จาก 0 ถึง N index แล้ว เราจะใช้ for loop ที่รันจนกว่า end ของ window จะยังน้อยกว่าความยาวอาร์เรย์ต้นฉบับ
ลูปนี้ตรวจสอบความเสถียรของ window (คือความยาว window เท่ากับ N) ถ้า window เสถียร เราใส่ window (subarray นั้น) ลง results array เลื่อนมันไปขวาหน่วยหนึ่ง และ collapse (start = end) ถ้า window ไม่เสถียร เราเพิ่มองค์ประกอบเข้าไปต่อ
โค้ดสำหรับวิธีนี้คือ −
ตัวอย่าง
const arr = [1, 2, 3, 4, 5]; const eachCons = function(num){ let res = [], temp = []; let start = 0, end = 0; while(end < num){ temp.push(this[end++]); }; for(; end <= this.length ;){ if(temp.length === num){ res.push(temp); start++; end = start; temp = []; } temp[end-start] = this[end]; end++; } return res; }; Array.prototype.eachCons = eachCons; console.log([1, 2, 3, 4, 5].eachCons(1)); console.log([1, 2, 3, 4, 5].eachCons(2)); console.log([1, 2, 3, 4, 5].eachCons(3)); console.log([1, 2, 3, 4, 5].eachCons(4));ผลลัพธ์
ผลลัพธ์ในคอนโซลจะเป็นดังนี้
[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ] [ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ], [ 4, 5 ] ] [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ] ] [ [ 1, 2, 3, 4 ], [ 2, 3, 4, 5 ] ]