บทนำ
List comprehension ทำให้สร้าง derived list จาก source list ได้ง่าย เช่น คูณทุกค่าด้วย 5
ปัญหา: รวมสองลิสต์ด้วยลูป
list1 = [100, 200, 300, 400]
list2 = [500, 600, 700, 800]
list3 = []
for i in range(len(list1)):
list3.append(list1[i] + list2[i])
# [600, 800, 1000, 1200]
ใช้ zip() รวม iterator แบบขนาน
list4 = [(a + b) for a, b in zip(list1, list2)]
# [600, 800, 1000, 1200]
zip จับคู่ element ตาม index: (100,500), (200,600), ... unpack เป็น a, b แล้วคำนวณ
ข้อควรระวังสำคัญ: zip หยุดเมื่อ iterator ใด iterator หนึ่งหมด
list1.append(1000) # list1 ยาว 5, list2 ยาว 4
list5 = [(a + b) for a, b in zip(list1, list2)]
# [600, 800, 1000, 1200] - ค่า 1000 หายไป! ไม่มี error แจ้งเตือน
อันตรายใน production เพราะข้อมูลหายเงียบๆ
โซลูชัน: ใช้ itertools.zip_longest
from itertools import zip_longest
list6 = []
for a, b in zip_longest(list1, list2):
if b is None:
print("<< handle missing in list2 >>")
elif a is None:
print("<< handle missing in list1 >>")
else:
list6.append(a + b)
# list6 = [600, 800, 1000, 1200] (ยังคงคำนวณเฉพาะคู่ที่ครบ)
# แต่เรารู้ว่ามีค่า missing 4 ค่า จาก print
zip_longest ยืด iterator สั้นด้วย None (default) จนกว่า iterator ยาวจะหมด สามารถกำหนด fillvalue ได้
สรุป
zipสะดวกสำหรับ iterate หลาย iterator พร้อมกันzipหยุดเมื่อ iterator ใด iterator หนึ่งหมด (อาจทำให้ข้อมูลหายโดยไม่รู้)- ถ้า iterator ความยาวต่างกัน ต้องใช้
itertools.zip_longestและจัดการ fillvalue เอง