หน้าเว็บ

วันอังคารที่ 19 สิงหาคม พ.ศ. 2557

การใช้เมธอด collect

มธอด collect เป็นหนึ่งในเมธอดของโมดูล Enumerable ที่มิกซ์อิน (mix-in) อยู่ในคลาสพื้นฐานอย่าง คลาส Array, Hash หรือ Struct
ในเบื้องต้นเราสามารถเรียกใช้เมธอด collect จากอ็อบเจกต์ที่เป็นอินสแตนซ์ของคลาสที่ว่าข้างต้น

เมธอด collect จะทำงานโดยการวนรอบสมาชิกแต่ละตัวของอ็อบเจกต์ที่เรียกใช้มัน (receiver) แล้วทำการรันโค้ดในบล็อก ค่าสุดท้ายที่รีเทิร์นจากการรันบล็อกในแต่ละรอบจะถูกเก็บลงไปในอาร์เรย์ ซึ่งอาร์เรย์ดังกล่าวจะเป็นอ็อบเจกต์ที่ถูกคืนกลับออกมาเมื่อเมธอด collect จบการทำงาน (วนรอบสมาชิกแต่ละตัวของอ็อบเจกต์ receiver จนหมด)

ประโยชน์ของ collect คือเราสามารถใช้มันเพื่อ "transform" ข้อมูลที่เราต้องการ
ลองดูตัวอย่างการใช้ เมธอด collect ดังต่อไปนี้

>> [1, 2, 3, 4, 5].collect { |x| x*5 }    => [5, 10, 15, 20, 25]
>> [65, 66, 67].collect { |x| x.chr }     => ["A", "B", "C"]

จะเห็นว่าเราสามารถใช้ collect เพื่อลองเปลี่ยนอาร์เรย์ของข้อมูลที่เป็นตัวเลขอย่าง [65, 66, 67] ให้กลายเป็นอาร์เรย์ของตัวอักษร ดังนี้ ซึ่งการแปลงร่างของเราอาศัยเมธอด chr ซึ่งจะมองค่าของตัวเลขที่เรียกใช้มันไปเป็นค่าของ ASCII code แล้วคืนค่าออกมาเป็นตัวอักษร
สังเกตุว่าในการวนรอบแต่ละรอบ ค่าของสมาชิกแต่ละตัวของอ็อบเจกต์ receiver (ในที่นี้คือ [65, 66, 67]) จะถูกโยนลงไปในบล็อก ซึ่งผลลัพธ์สุดท้ายที่ได้จากการรันบล็อกในแต่ละรอบจะถูกเก็บลงไปในอาร์เรย์ เมื่อวนรอบจนครบ
ค่าของอาร์เรย์ดังกล่าวก็จะถูกคืนออกมาเป็นค่า return ของเมธอด collect ซึ่งในที่นี้ก็คือ ["A", "B", "C"] นั่นเอง

collect จะคืนค่าออกมาเป็นอาร์เรย์ที่มีจำนวนสมาชิกเท่ากับจำนวนสมาชิกของอ็อบเจกต์ตั้งต้นเสมอ เช่น

[1, 2, 3, 4, 5].collect do |x|
  x*5 if x > 3
end

=> [nil, nil, nil, 20, 25]

คุณอาจจะไม่ค่อยคุ้น หรือยังนึกไม่ออกว่าจะใช่ collect ตอนไหน ถ้าคุณพบว่าคุณมักจะเขียนโค้ด ออกมาในรูปแบบนี้ ...

def my_transform(data)
  a = []
  data.each do |x|
    # do something that manipulate x
    a << "#{x}!!!"
  end
  return a
end

puts my_transform([1,2,3])

ซึ่งให้ผลลัพธ์ดังนี้
1!!!
2!!!
3!!!

แต่คุณสามารถใช้ collect เพื่อนำปรับปรุงโค้ดใหม่ โดยให้ผลลัพธ์เหมือนเดิมได้ดังนี้

def my_transform2(data)
  data.collect { |x| "#{x}!!!" }
end

puts my_transform2([1,2,3])

ในโค้ดใหม่ คุณจะเห็นว่าเราไม่จำเป็นต้อง setup ตัวแปรโลคอลอย่าง a ขึ้นมา เพราะว่าเมธอดค่าที่คืนออกมาจาก collect นั้นเป็นอาร์เรย์อยู่แล้ว

ลองนำไปใช้ดูนะครับ

ไม่มีความคิดเห็น:

แสดงความคิดเห็น