ทบทวนพื้นฐาน: List Comprehensions และ map()
ก่อนที่เราจะพูดถึงการใช้งานร่วมกัน มาทบทวนบทบาทของแต่ละฟังก์ชันโดยย่อ:
- List Comprehensions:
- เป็นรูปแบบการสร้างลิสต์ใหม่ที่สั้น กระชับ และอ่านง่าย โดยสามารถรวมการแปลงข้อมูล (mapping) และการกรองข้อมูล (filtering) เข้าไว้ในบรรทัดเดียว มักเป็นที่นิยมสำหรับงานที่ตรงไปตรงมาและต้องการสร้างลิสต์ใหม่จาก Iterable เดิม
รูปแบบ:ตัวอย่าง:โค้ด: เลือกทั้งหมด
[expression for item in iterable if condition]
โค้ด: เลือกทั้งหมด
squared_numbers = [x**2 for x in [1, 2, 3]]
- เป็นฟังก์ชัน Built-in ที่ใช้สำหรับ "ประยุกต์ใช้" ฟังก์ชันที่ระบุลงบนสมาชิกแต่ละตัวของ Iterable และส่งคืน map object (ซึ่งเป็น Iterator) มักใช้เมื่อมีฟังก์ชันที่คุณต้องการนำไปใช้กับสมาชิกจำนวนมาก หรือเมื่อต้องการประมวลผลแบบ Lazy Evaluation (ประมวลผลทีละตัวเมื่อถูกเรียกใช้)
รูปแบบ:ตัวอย่าง:โค้ด: เลือกทั้งหมด
map(function, iterable, ...)
โค้ด: เลือกทั้งหมด
squared_numbers = list(map(lambda x: x**2, [1, 2, 3]))
โดยทั่วไปแล้ว List Comprehensions และ map() มักถูกใช้เป็น ทางเลือก ซึ่งกันและกันสำหรับการแปลงข้อมูล อย่างไรก็ตาม มีบางสถานการณ์ที่คุณอาจพบว่ามีการใช้งานร่วมกัน (แต่ส่วนใหญ่อาจไม่ใช่การ "ซ้อนกัน" โดยตรง) ดังนี้:
สถานการณ์ที่ 1: ใช้ List Comprehensions เพื่อแปลง map Object เป็น List (พบบ่อยที่สุด)
เนื่องจาก map() คืนค่าเป็น map object (ซึ่งเป็น Iterator) เพื่อประหยัด Memory และประมวลผลแบบ Lazy Evaluation คุณมักจะต้องแปลง map object ให้เป็นลิสต์จริงๆ เพื่อนำไปใช้งานต่อ หรือเพื่อดูผลลัพธ์ทั้งหมด และวิธีหนึ่งที่ทำได้คือการใช้ List Comprehensions (แม้ว่า list() constructor จะเป็นวิธีที่ตรงกว่า)
ตัวอย่าง: แปลงสตริงในลิสต์ให้เป็นตัวพิมพ์ใหญ่ด้วย map() จากนั้นประมวลผลเพิ่มเติมด้วย List Comprehensions (ในตัวอย่างนี้อาจดูไม่จำเป็น แต่แสดงให้เห็นการไหลของข้อมูล)
โค้ด: เลือกทั้งหมด
words = ["hello", "world", "python"]
# 1. ใช้ map() เพื่อแปลงเป็นตัวพิมพ์ใหญ่ (ผลลัพธ์คือ map object)
uppercase_map_object = map(str.upper, words)
print(f"Type of map object: {type(uppercase_map_object)}") # Output: <class 'map'>
# 2. ใช้ List Comprehension เพื่อดึงค่าจาก map object และสร้าง list ใหม่
# และในขณะเดียวกันก็เพิ่มข้อความ "!" ท้ายคำ
final_words = [word + "!" for word in uppercase_map_object]
print(f"Final words: {final_words}") # Output: Final words: ['HELLO!', 'WORLD!', 'PYTHON!']
สถานการณ์ที่ 2: ใช้ map() เพื่อเตรียมข้อมูลสำหรับ List Comprehensions (ไม่ค่อยพบบ่อยนัก)
เป็นไปได้ที่จะใช้ map() เพื่อประมวลผลเบื้องต้นกับข้อมูลจำนวนมากก่อน แล้วค่อยส่งผลลัพธ์ที่เป็น map object (ซึ่งเป็น Iterator) เข้าไปใน List Comprehensions เพื่อประมวลผลต่อพร้อมกับเงื่อนไขการกรอง
ตัวอย่าง: ประมวลผลตัวเลขโดยใช้ map() เพื่อยกกำลังสองก่อน แล้วค่อยใช้ List Comprehensions กรองเฉพาะตัวเลขคู่
โค้ด: เลือกทั้งหมด
numbers = [1, 2, 3, 4, 5, 6]
# 1. ใช้ map() เพื่อยกกำลังสอง (ผลลัพธ์คือ map object)
squared_numbers_map = map(lambda x: x**2, numbers)
# 2. ใช้ List Comprehensions เพื่อกรองเฉพาะตัวเลขคู่จากผลลัพธ์ของ map
even_squared_numbers = [num for num in squared_numbers_map if num % 2 == 0]
print(f"Even squared numbers: {even_squared_numbers}")
# Output: Even squared numbers: [4, 16, 36]
สรุป: เมื่อไหร่ควรใช้อะไร?
- เลือก List Comprehensions เป็นอันดับแรก: สำหรับงานส่วนใหญ่ที่เกี่ยวข้องกับการแปลงและ/หรือกรองข้อมูลจาก Iterable เพื่อสร้างลิสต์ใหม่ โดยเฉพาะอย่างยิ่งเมื่อโค้ดมีความซับซ้อนไม่มาก และต้องการผลลัพธ์เป็นลิสต์ทันที List Comprehensions มักจะอ่านง่ายกว่า
- เลือก map():
- เมื่อคุณมีฟังก์ชันที่ซับซ้อนที่ประกาศไว้อยู่แล้ว และต้องการนำไปใช้กับ Iterable โดยไม่ต้องสร้าง lambda ที่ยาวหรือซับซ้อน
เมื่อคุณต้องการประหยัด Memory สำหรับชุดข้อมูลขนาดใหญ่มากๆ โดยต้องการผลลัพธ์เป็น Iterator (Lazy Evaluation) และจะวนซ้ำแค่บางส่วนหรือประมวลผลทีละตัว
- สถานการณ์ที่พบบ่อยที่สุดคือการใช้ List Comprehensions หรือ list() เพื่อ ดึงค่าจาก map object และแปลงให้เป็นลิสต์ที่ใช้งานได้
การใช้ map() เพื่อทำ "Pre-processing" บางอย่างกับชุดข้อมูลขนาดใหญ่ ก่อนที่จะส่งผ่านเข้าสู่ List Comprehensions เพื่อการกรองหรือประมวลผลขั้นสุดท้าย ก็เป็นไปได้ แต่ต้องพิจารณาความจำเป็นและความชัดเจนของโค้ด
- https://www.mindphp.com/คู่มือ/73-คืออะ ... ออะไร.html
- viewtopic.php?t=45663
- https://www.mindphp.com/บทเรียนออนไลน์/ ... -type.html
- https://www.mindphp.com/บทเรียนออนไลน์/ ... -type.html
- viewtopic.php?t=107367
- viewtopic.php?t=116403