Python มี syntax ที่ช่วยให้เราเขียนโค้ดได้ง่ายและสั้นขึ้นหลายอย่าง แต่วันนี้เราจะมาดูประโยชน์และวิธีการใช้งาน comprehension statements ใน python กัน
Comprehension statements ใน python เป็น syntax สั้นๆ ที่ช่วยให้เราสามารถเขียนโค้ดเพื่อสร้างตัวแปร Lists, dictionaries หรือ sets ใหม่จากตัวแปร iterables ที่มีอยู่ได้อย่างง่ายดาย
ตัวอย่างเช่น หากเรามีตัวเลขใน List อยู่และต้องการที่จะสร้าง List ใหม่เป็นค่ายกกำลังสองของเลขชุดเดิม ถ้าเขียนแบบไม่ใช้ comprehension statement เราจะเขียนออกมาได้ดังโค้ดข้างล่างนี้
numbers = [0, 1, 2, 3, 4]
squares = []
for number in numbers:
squares.append(number * number)
ซึ่งหากเรา print ค่า squares ออกมาดู ก็จะได้ค่า [0, 1, 4, 9, 16] ตามที่เราอยากได้ แต่ใน python เราสามารถใช้ comprehension statement เขียนโค้ดที่ทำงานแบบเดียวกันได้ใหม่ดังนี้
numbers = [0, 1, 2, 3, 4]
squares = [number * number for number in numbers]
หากเรา print ค่าออกมาดูก็จะได้ผลลัพธ์เหมือนก่อนหน้านี้ตามที่เราคาดหวัง จากตัวอย่างโค้ดข้างต้น เราก็พอที่จะสรุป รูปแบบ syntax ของ comprehension statements ได้ดังนี้
new_list = [expression for item in old_list]
Comprehension statements แบบมีเงื่อนไข
คราวนี้หากเราต้องการสร้างเงื่อนไขในการสร้าง List ใหม่ เช่น เราต้องการค่ายกกำลังสองของเลขคี่จาก List ต้นทาง เราจะเขียนยังไง?
ข่าวดีคือเราสามารถกำหนดเงื่อนไขใน Comprehension statements ได้ง่ายๆดังตัวอย่างข้างล่างนี้
numbers = [0, 1, 2, 3, 4]
odd_squares = [number * number for number in numbers if number % 2 == 1]
หากเรา print ค่า odd_squares ออกมา เราจะได้ค่า [1, 9] ซึ่งเป็นค่ายกกำลังสองของ 1 และ 3 ซึ่งเป็นเลขคี่ใน List ต้นทางเท่านั้น ซึ่งทำให้เราสามารถอัพเดตรูปแบบ syntax ของ comprehension statement ได้ดังนี้
new_list = [expression for item in old_list if condition]
Comprehension statements สำหรับ Set
นอกจากการใช้ comprehension statements เพื่อสร้าง List แล้ว เรายังสามารถสร้าง set ได้ด้วย โดยเราแค่เปลี่ยนจาก [] เป็น {} เท่านั้นเอง หากเราเปลี่ยนตัวอย่างข้างบนมาใส่ set แทน เราจะเขียนโค้ดได้ดังนี้
numbers = [0, 1, 2, 3, 4]
square_set = {number * number for number in numbers}
หากเรา print ค่า square_set ออกมา เราก็จะได้ค่าเป็น {0, 1, 4, 9, 16} ตามที่เราคาดหวัง และเรายังสามารถใส่เงื่อนไขได้เหมือนการเขียน list comprehension
หากท่านไม่รู้ความแตกต่างระหว่าง List กับ Set ความแตกต่างหลักๆของมันคือ List มีค่าที่ซ้ำกันได้ ส่วน set จะไม่เก็บค่าซ้ำลงไป เช่นหาก set มีค่า 1 อยู่แล้ว หากเราพยายามจะใส่ 1 เข้าไปอีก ก็จะไม่มีการเปลี่ยนแปลงอะไรใน set ไว้หากมีโอกาสจะมาเขียนบทความอธิบายเรื่องนี้กันอีกทีครับ
Comprehension statements สำหรับ dictionary
เรามี comprehension statements สำหรับ list และ set ไปแล้ว แน่นอนเราก็ควรต้องมีตัวอย่างสำหรับ dictionary หลักการการใช้งานนั้นเหมือนเดิมเลย เพียงแค่มีการปรับ syntax เล็กน้อย จากตัวอย่างเดิม หากเราได้อยากได้ dictionary ที่ระบุค่า key เป็นตัวเลข และ value ของมันคือค่ากำลังสองของ key เราจะเขียนได้ดังนี้
numbers = [0, 1, 2, 3, 4]
square_dict = {number: number * number for number in numbers}
หากเรา print(square_dict) เราก็จะได้ผลลัพธ์เป็น {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} ซึ่งเป็นไปตามที่เราคาดหวัง และแน่นอนเหมือนที่เราเคยทำเราสามารถใส่เงื่อนไขลงไปได้ เช่น หากเราต้องการเลือกเฉพาะ number ที่มากกว่า 1 เราก็สามารถเขียนได้ดังนี้
numbers = [0, 1, 2, 3, 4]
square_dict = {number: number * number for number in numbers if number > 1}
เมื่อเรา print(square_dict) เราก็จะได้ผลลัพธ์เป็น {2: 4, 3: 9, 4: 16}
The zip function
อีกตัวอย่างหนึ่งที่ผมอย่างแสดงให้ดูและโชว์ทางเลือกในการใช้งานด้วยคือตัวอย่างข้างล่างนี้
names = ["John", "Jim", "Jack"]
ages = [28, 32, 17]
age_profiles = {names[i]: ages[i] for i in range(len(names))}
จากตัวอย่างข้างต้นหากเรา print(age_profiles) เราจะได้ผลลัพธ์เป็น {‘John’: 28, ‘Jim’: 32, ‘Jack’: 17} จะเห็นว่าเราสามารถที่จะทำ list สองอันมาสร้างเป็น dictionary ตัวใหม่ได้โดยให้ list นึงเป็น key และอีก list เป็น value
เมื่อกี้ผมบอกว่าจะโชว์ทางเลือกในการทำให้ได้ผลลัพธ์แบบเดียวกัน ซึ่งวิธีการก็คือการใช้ฟังก์ชัน zip ซึ่งเราสามารถเขียนได้ดังนี้
names = ["John", "Jim", "Jack"]
ages = [28, 32, 17]
age_profiles = dict(zip(names, ages))
หากเรา print(age_profiles) ออกมาก็จะได้ผลลัพธ์ที่ตามที่เราต้องการ หากอยากอ่านเพิ่มเติมเกี่ยวกับฟังก์ชัน zip สามารถไปดูได้ที่นี่
นอกจากนี้เรายังสามารถที่จะเขียน for ซ้ำเข้าไปใน comprehension statement ได้ แต่ผมไม่แนะนำให้ทำเพราะมันจะเริ่มทำให้โค้ดดูซับซ้อนเกินไปซึ่งไม่ตรงจุดประสงค์ของการใช้ comprehension statement เราใช้ comprehension statement เพื่อให้โค้ดสั้น กระชับและอ่านง่าย หากใช้แล้วอ่านยากขึ้น เราก็ไม่ควรจะใช้ครับ
โดยสรุปแล้วการใช้ comprehension statements มีประโยชน์ในการช่วยให้โค้ดดูกระชับและอ่านง่ายขึ้น รวมไปถึงการจัดการ memory ที่ดีขึ้นในบางกรณี อย่างไรก็ตามหากเราถนัดที่จะเขียน for loop แบบเดิม ก็ไม่มีความจำเป็นต้องใช้ comprehension statements ครับ แต่อย่างน้อยที่สุดเราควรจะรู้จัก syntax เอาไว้เพื่อให้อ่านโค้ดได้ เพราะในการทำงานจริงเราจะต้องทำงานเป็นทีมและมีการเขียนโค้ดร่วมกับผู้อื่น ซึ่งโปรแกรมเมอร์คนอื่นอาจจะใช้ comprehension statements ก็ได้ ดังนั้นหากเรารู้จัก comprehension statements ก็จะทำให้เราสามารถทำงานได้ง่ายขึ้นไปด้วย