ขี้เกียจเขียน For loop ภาค 2

หลังจากคราวที่ผมได้มาเล่าไปแล้วว่าผมเอาตัวรอดในฐานะโปรแกรมเมอร์มาได้ไงเป็นเวลากว่าปีโดยไม่ใช้ for loop ใครยังไม่ได้ติดตามความขี้เกียจครั้งที่แล้ว เชิญติดตามได้ทางลิงค์นี้ครับ ขี้เกียจเขียน For loop คราวนี้ จะมาเล่าถึงเทคนิคนึง ซึ่งผมเพิ่งได้เรียนรู้เมื่อไม่กี่เดือนมานี้เอง คิดว่าน่าจะมีประโยชน์กับท่านที่สนใจศาสตร์ทาง functional programming และ immutable data ไม่มากก็น้อย

ปัญหาก็มีอยู่ว่า เมื่อเราไม่มี for loop แล้ว ไม่มีไอ่เจ้า i++ แล้ว ถ้าเราจำเป็นต้องใช้เจ้าตัวเลขลำดับ (i) นี้จะทำยังไง

ตัวอย่างของปัญหาในครั้งนี้ คือ ฟอร์แมทผลลัพธ์ของการแข่งขันเขียนโปรแกรม ซึ่งไม่ว่าจะเป็นทั้ง Google Code Jam หรือ Facebook Hacker Cup จะผู้แข่งขันสร้างไฟล์สำหรับผมลัพธ์ซึ่งมีหน้าตาเป็นแบบนี้

Case #1: 100
Case #2: 200
Case #3: 300
...

เราจะมาเขียน code ที่รับอาเรย์ของผลลัพธ์แต่ละข้อมา(เช่น [100,200,300,…]) แล้วสร้าง string ของฟอร์แมทผลลัพท์เหมือนด้านบนกัน โดยอย่าลืมว่าเราไม่มี for loop นะ

เริ่มต้นด้วยวิธีแรกที่ชาว Ruby นิยมใช้กัน each_with_index

output = [100,200,300]
result = ''
output.each_with_index do |e,i|
  result += "Case ##{i+1}: #{e}\n"
end
puts result

วิธีนี้ใช้ได้ดีครับ ติดอยู่เพียงแค่ว่ามันมีการ assign ค่าใหม่หลายครั้งให้แก่ตัวแปร result ไม่ถูกใจขาโจ๋ pure function, immutable data อย่างเราเลย

มาดูวิธีต่อไป วิธีนี้ไม่มีการ assign ค่าให้แก่ตัวแปรเลย แต่ขออนุญาตสงวนสิทธิ์ห้ามลอกเลียนแบบนำไปใช้นะครับ ผมเคยใช้วิธีนี้ตอนสมัยหัด functional programming ใหม่ๆ ด้วย Scala เอาไปแข่ง Code Jam ครับ ผลลัพธ์ครับ ทำไม่เสร็จซักข้อครับ

วิธีนั้นคือ recursive ครับ

def results(a, i)
  if a.empty?
    ''
  else
    "Case ##{i}: #{a.first}\n" + results(a[1..-1], i+1)
  end
end
results([100,200,300], 1)

เหนื่อยมากครับ แต่ก็ถือว่าเอาตัวรอดมาได้ แบบไม่ต้องมีการ assign ตัวแปรเลยครับ

มาดูวิธีที่สามกันบ้าง ซึ่งเป็นวิธีที่แสดงเทคนิคที่ทำให้ผมมานั่งเขียน blog นี้กันครับ

 output = [100,200,300]
 index = (1..output.length).to_a
 output.zip(index).map { |(e,i)| "Case ##{i}: #{e}" }.join("\n")
 

เทคนิคมันอยู่ตรงไอ่เจ้า zip นี่แหละครับ ในเมื่อไม่มี i ก็หา i มาแปะเข้าไปซะเลย คราวนี้ก็จะได้คู่ตัวเลข e และ i ไปทำอะไรก็ได้ตามใจเราครับ จะประยุกต์ให้เป็น i+2, i*8 ยังไงตามใจเรา เลือกสร้างอาเรย์ของ “i” แบบตัวแปร index ได้ตามความเหมาะสมเลยครับ

เจ้า zip นี้ชื่ออาจจะต่างกันไปในแต่ละภาษาครับ โดยการทำงานของมันคือเอาอาเรย์มา 2 (หรือหลายอัน) แล้วสร้างอาเรย์ใหม่โดยกรุ๊ปค่าในตำแหน่งเดียวกันเข้าด้วยกันครับ

Advertisements

One thought on “ขี้เกียจเขียน For loop ภาค 2

  1. Pingback: ขี้เกียจเขียน For loop ภาค 3 – ของจริง! « Tap

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s