Enumerable คืออะไร?
Enumerable คือ ชุดของ iteration methods เป็น Ruby module และเป็นส่วนสำคัญที่ทำให้ Ruby เป็นภาษาโปรแกรมมิ่งที่ยอดเยี่ยม
Enumerable รวมเมธอดที่มีประโยชน์อย่าง:
mapselectinject
Enumerable methods ทำงานโดยรับ block ใน block คุณบอกว่าอยากทำอะไรกับแต่ละ element
เช่น:
[1,2,3].map { |n| n * 2 }
ได้ array ใหม่ที่เลขทุกตัวคูณ 2 แล้วพอดีสิ่งที่เกิดขึ้นขึ้นอยู่กับเมธอดที่ใช้ map transform values, select filter list, inject รวมค่าใน array
มี Ruby Enumerable methods มากกว่า 20 ตัว มาศึกษาตัวหนึ่งละเอียด
เมธอด Each_Cons
เมธอด Enumerable โปรดใหม่ของผมคือ each_cons!
เหตุผล: เมธอดนี้มีประโยชน์มาก ใช้หา n-grams หรือเช็กว่า sequence ของเลขเป็น contiguous ได้เมื่อรวมกับ all? อีกเมธอด Enumerable

each_cons ให้ sub-arrays ขนาด n เช่น [1,2,3] แล้ว each_cons(2) จะได้ [[1,2], [2,3]]
ตัวอย่าง:
numbers = [3,5,4,2]
numbers.sort.each_cons(2).all? { |x,y| x == y - 1 }
โค้ดนี้ sort เลข แล้ว each_cons(2) คืน Enumerator object แล้วเรียก all? เช็กเงื่อนไขทั้งหมด
อีกตัวอย่าง ใช้ each_cons เช็กว่า character ถูกล้อมรอบด้วย character เดียวกัน เช่น xyx:
str = 'abcxyx'
str.chars.each_cons(3).any? { |a,b,c| a == c }
ยังมีอีก! ถ้าอยากรู้ pattern นี้เกิดกี่ครั้ง แทน true/false แค่เปลี่ยน any? เป็น count
สิ่งที่น่าสนใจกว่านั้นคือ implementation ของ each_cons:
array = [] each do |element| array << element array.shift if array.size > n yield array.dup if array.size == n end
หมายเหตุ: มาจาก Rubinius implementation ของ
Enumerableหา source code ได้ที่นี่
Implementation เริ่มจาก empty array แล้ว iterate ผ่าน elements ด้วย each ทุกอย่างปกติจนกว่าจะเพิ่ม element เข้า array และ trim array (ด้วย Array#shift) ถ้าขนาดใหญ่กว่าที่ต้องการ size คือ argument ของ each_cons แล้ว yield dup ของ array ถ้าขนาดตรงกับที่ขอ ผมคิดว่าเป็น genius เพราะสร้าง 'sliding window' effect แทนที่จะมานั่งจัดการ array indexes
เมธอดน่าสนใจอีกมากมาย
| Method | คำอธิบาย |
|---|---|
| count | นับสิ่งที่ evaluate เป็น true ใน block |
| group_by | จัดกลุ่ม elements ตามค่า return ของ block คืนค่า hash |
| partition | แบ่งเป็น 2 กลุ่ม คืนค่า 2D array |
| any? | คืน true ถ้า block คืน true สำหรับ ANY element |
| all? | คืน true ถ้า block คืน true สำหรับ ALL elements |
| none? | ตรงข้ามของ all? |
| cycle(n) | ทำซ้ำ ALL elements n ครั้ง เช่น [1,2].cycle(2) ได้ [1,2,1,2] |
| find | คล้าย select แต่คืนแค่ตัวแรกที่เจอ |
| inject | สะสมผลลัพธ์ block ก่อนหน้า ส่งต่อไปอันถัดไป เหมาะสำหรับ sum totals |
| zip | รวม 2 enumerable objects ทำงานแบบ parallel เหมาะสำหรับเปรียบเทียบและสร้าง hashes |
| map | transform ทุก element คืน array ใหม่ |
ปิดท้าย
เห็นได้ว่า Enumerable เป็น module ที่คุ้มค่าที่จะ master ไปอ่าน documentation ดูว่ามันทำอะไรให้คุณได้บ้าง!
อย่าลืมแชร์และสมัครรับ newsletter ในฟอร์มด้านล่างถ้าชอบบทความนี้ จะช่วยผมเยอะมาก! 🙂