for loop (Control Structure 3)
การทำซ้ำมี 3 ส่วนประกอบเสมอ
ส่วนประกอบของการทำซ้ำ มี 3 ส่วน
True) หรือไม่TrueFalsex<10, x>-5, x<=99, ans!="y"x=0, y=100, ans="n"x=x+1, x+=10, x-=1, ans = input()Note
สร้างลำดับตัวเลขจำนวนเต็มไว้ล่วงหน้า
range() functionจากส่วนประกอบทั้งสามของการทำซ้ำ ซึ่งเป็นรูปแบบที่ใช้คู่กับคำสั่ง while ดังตัวอย่างที่พิมพ์เลข 1 3 5 7
range() แบบที่ 1ค่าแรกเริ่มที่ START เพิ่มค่าขึ้นทีละ STEP โดยค่าสุดท้ายคือค่าจำนวนเต็มก่อนถึงค่า STOP (ไม่รวม STOP)
ตัวอย่าง: range(5, 20, 2) ได้ลำดับ 5, 7, 9, 11, 13, 15, 17, 19
(START=5, STOP=20, STEP=2)
range() ทำงานยังไงrange(1, 9, 2) — เริ่มที่ START ก้าวทีละ STEP จนก่อนถึง STOP (ไม่รวม STOP)
ได้ลำดับ 1, 3, 5, 7 — ค่า 9 (STOP) ถูกตัดทิ้ง ไม่รวมในลำดับ
range() ↔︎ Slice: โครงเดียวกันrange() ใช้ start : stop : step แบบเดียวกับ slice ที่เคยเรียนกับ List — และ ไม่รวม STOP เหมือนกัน!
Slice — ตัดช่วงจาก list ที่มีอยู่
data[1:9:2]
start · stop (ไม่รวม) · step — เหมือนกันทั้งคู่!
Note
ทบทวน: Slice ของ List (Module 4a)
จงใช้ range() สร้างลำดับเลข 2, 6, 10, 14, 18
จงใช้ range() สร้างลำดับเลข 10, 7, 4
Tip
คิดก่อน: ลำดับนี้ค่าลดลง → STEP ต้องเป็นค่าใด?
range() แบบที่ 2ค่าแรกเริ่มที่ START เพิ่มค่าขึ้นทีละ 1 (STEP=1) ไปจนถึงค่าจำนวนเต็มก่อนถึงค่า STOP (ไม่รวม STOP)
ตัวอย่าง: range(3, 6) คือ 3, 4, 5
(START=3, STOP=6, STEP=1)
จงใช้ range() โดยละการกำหนด STEP ในการสร้างลำดับเลข 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
range() แบบที่ 3ค่าแรกเริ่มที่ 0 (START=0) เพิ่มค่าขึ้นทีละ 1 (STEP=1) ไปจนถึงค่าจำนวนเต็มก่อนถึงค่า STOP (ไม่รวม STOP)
ตัวอย่าง: range(6) คือ 0, 1, 2, 3, 4, 5
จงใช้ range() โดยละการกำหนด START และ STEP ในการสร้างลำดับเลข 0, 1, 2, ..., 10
จำนวนค่าที่ได้จากคำสั่ง range() คำนวณได้จากสูตร
\[ \text{จำนวนค่า} = \bigg\lceil\frac{\text{STOP} - \text{START}}{\text{STEP}}\bigg\rceil \]
โดย \(\lceil\cdot\rceil\) หมายถึงปัดขึ้น เช่น
range(2,20,4) ได้ \(\lceil\frac{20-2}{4}\rceil = 5\)range(2,20,3) ได้ \(\lceil\frac{20-2}{3}\rceil = 6\)range(10,1,-3) ได้ \(\lceil\frac{1-10}{-3}\rceil = 3\)ตรวจสอบจำนวนค่าได้ด้วย len()
ทำซ้ำตามลำดับค่า (iterable)
forfor เป็นคำสั่งที่ใช้ในการทำซ้ำ แต่มีรูปแบบการใช้ต่างจาก while
while statement ได้iterable (ลำดับค่าที่ไล่ดึงเป็นลำดับได้) ซึ่งอาจสร้างจาก range(), เป็น list หรือ str ก็ได้for ดึงค่าทีละตัวfor i in [10, 20, 30]: — ตัวแปร i รับค่าจาก iterable รอบละ 1 ค่า ตามลำดับ
ครบทุกค่าใน iterable แล้ว → ออกจากลูป (ไม่ต้องเขียน i += 1 เอง!)
for กับส่วนประกอบของลูปส่วน Initialization, Condition, และ Update ของลูป for แฝงตัวอยู่ในบรรทัด for i in iterable
เทียบกับแผนภาพของลูป while จะได้ว่า
for — 3 ส่วนซ่อนในบรรทัดเดียว
for i in range(1, n+1, 1):
i เริ่มที่ 1i < n+1i รับค่าถัดไปwhile — เขียนแยก 3 ส่วน
i = 1 while i <= n: print(i) i += 1
สีเดียวกัน = ส่วนเดียวกัน — for แค่ย่อ 3 ส่วนไว้บรรทัดเดียว
Note
ทบทวน: while-loop (Module 6)
โปรแกรมแสดงเลข 1 ถึง n ด้วย while เป็นดังนี้
จงเขียนโปรแกรมที่ให้ผลลัพธ์เดียวกัน โดยใช้คำสั่ง for
โปรแกรมที่ใช้ลูป for ยังคงส่วนประกอบ ดังนี้
i = 1i <= ni += 1Note
ส่วนประกอบเหล่านี้แฝงในคำสั่ง for i in range(1, n+1) จึงต้องอาศัยการตีความ
โปรแกรมแสดงสูตรคูณแม่ n (\(1\times n\) ถึง \(12\times n\)) ด้วย while
จงเขียนโปรแกรมที่ให้ผลลัพธ์เดียวกัน โดยใช้คำสั่ง for (พิมพ์ขึ้นบรรทัดใหม่ทุก 5 ค่า)
Note
โปรแกรมที่ใช้ลูป for ยังคงส่วนประกอบ ดังนี้
i = 1i < 13i += 1หาผลบวกกำลังสองของเลขคี่ระหว่าง 1 ถึง n
\[ \text{Sum} = n^2 + (n-2)^2 + ... + 5^2 + 3^2 + 1^2 \]
โปรแกรมเดิมเขียนด้วย while (ไล่ค่า n ลงมาทีละ 1)
จงเขียนใหม่โดยใช้ลูป for ที่ไล่ค่าจาก n ลงมาถึง 1
Note
โปรแกรมที่ใช้ลูป for มีส่วนประกอบ ดังนี้
i = n (n = input())i > 0i -= 1จงเขียนโปรแกรมหาค่าเฉลี่ย (Average) ของข้อมูล n ตัว
\[ \text{avg} = \frac{\text{Sum}}{n} = \frac{\text{data}_1 + \text{data}_2 + ... + \text{data}_n}{n} \]
สร้างตัวแปร Sum = 0.0
วนลูป for รับค่า data แต่ละตัว (แปลงเป็น float) แล้วบวกทบ Sum
คิดก่อน: คำนวณค่าเฉลี่ยจาก Sum และ n อย่างไร?
ลูปภายในลูป — ลูปในจบก่อน ลูปนอกจบทีหลัง
หัวข้อที่ผ่านมาใช้ลูปเพียงชั้นเดียว ในทางปฏิบัติสามารถเรียกใช้แบบลูปซ้อนกันได้ ทั้ง while และ for ผสมกัน
for i in range(1,4): (นอก) · for j in range(1,4): (ใน) → ลูปในวิ่งครบ ก่อนลูปนอกขยับ 1 ขั้น
🔴 เลขในวงกลม = ลำดับการทำงาน (1→9) · แต่ละแถว (สี) = ลูปใน j วิ่งครบก่อน ลูปนอก i จึงเปลี่ยนแถว
จากโจทย์ #5a จงเพิ่มความสามารถให้คำนวณค่าเฉลี่ยได้หลายชุด
เมื่อคำนวณค่าเฉลี่ย 1 ชุดเสร็จ ให้รับค่า n ใหม่เพื่อคำนวณชุดถัดไป (ไม่ออกโปรแกรม)
หากค่า n ที่รับมาเป็น n <= 0 ให้จบการทำงาน
คิดก่อน: จะนำโค้ดจาก #5a มาครอบด้วยลูปอะไร? เงื่อนไขใด?
Outer while-loop
n = input()n > 0n = input()Inner for-loop
i = 0i < ni += 1จงเขียนโปรแกรมพิมพ์อักษรภาพต่อไปนี้ โดยใช้ลูป for 2 อันซ้อนกัน
* 1 2 3 4 5 6 7
0 * 2 3 4 5 6 7
0 1 * 3 4 5 6 7
0 1 2 * 4 5 6 7
0 1 2 3 * 5 6 7
0 1 2 3 4 * 6 7
0 1 2 3 4 5 * 7
0 1 2 3 4 5 6 *
วิธีคิด: พิมพ์ให้จบทีละบรรทัด (ลูปใน ไล่คอลัมน์) แล้วขึ้นบรรทัดใหม่ทีละแถว (ลูปนอก ไล่แถว) — ตำแหน่งแนวทแยง (r == c) พิมพ์ * มิฉะนั้นพิมพ์เลขคอลัมน์ c
Note
ข้อสังเกต: ทุก 1 รอบของ outer loop จะมี inner loop ทำงาน ncol รอบ
จากโจทย์ #6 จงดัดแปลงโดยใช้ break ให้พิมพ์เฉพาะส่วนสามเหลี่ยมล่าง (ค่าด้านขวาของ * หายไป)
*
0 *
0 1 *
0 1 2 *
0 1 2 3 *
0 1 2 3 4 *
0 1 2 3 4 5 *
0 1 2 3 4 5 6 *
วิธีคิด: หลังพิมพ์ * ภายใต้เงื่อนไข r == c ให้ break ออกจากลูปในทันที เพื่อไปขึ้นบรรทัดใหม่
break ในลูปซ้อน ออกแค่ลูปในbreak หยุด เฉพาะลูปใน (c) ของแถวนั้น — ลูปนอก (r) เดินต่อ ไปแถวถัดไป
cr==c → พิมพ์ * แล้ว breakr เดินต่อ ลงแถวถัดไปสรุป: break ในลูปซ้อน ออกจากลูปในสุดชั้นเดียว ไม่ได้ออกทั้งหมด
จากโจทย์ #6 จงดัดแปลงโดยใช้ continue เพื่อข้ามการพิมพ์อักษร * (ดอกจันแนวทแยงหายไป)
1 2 3 4 5 6 7
0 2 3 4 5 6 7
0 1 3 4 5 6 7
0 1 2 4 5 6 7
0 1 2 3 5 6 7
0 1 2 3 4 6 7
0 1 2 3 4 5 7
0 1 2 3 4 5 6
วิธีคิด: ขณะวนลูปในและอยู่ภายใต้เงื่อนไข r == c ให้แทรก continue ก่อนที่จะพิมพ์ * ลูปในจะกลับไปรับค่า c ค่าใหม่ทันที
continue ในลูปซ้อน ข้ามแค่รอบเดียวcontinue ข้าม เฉพาะช่องแนวทแยง (r==c) — แถวยังพิมพ์ต่อจนครบ (ต่างจาก break)
c ตามปกติr==c → continue ข้ามช่องนี้c ที่เหลือ ยังพิมพ์ต่อต่างจาก break: break ตัดท้ายแถว · continue เว้นแค่ช่องเดียว
จากโจทย์ #7 จงดัดแปลงโดยใช้ continue เพิ่ม เพื่อพิมพ์แถวเว้นแถว (ข้ามแถวที่ r เป็นเลขคี่)
*
0 1 *
0 1 2 3 *
0 1 2 3 4 5 *
วิธีคิด: สั่ง continue ที่ ลูปนอก แต่ก่อนลูปใน ถ้าค่า r เป็นเลขคี่ ให้ข้ามการพิมพ์ทั้งบรรทัด
break + continue คนละระดับcontinue ที่ ลูปนอก → ข้ามทั้งแถว (แถวคี่) · break ที่ ลูปใน → ตัดท้ายแถว (แถวคู่)
🟠 continue (ลูปนอก) จัดการ ระดับแถว · 🔴 break (ลูปใน) จัดการ ระดับคอลัมน์ — แต่ละคำสั่งมีผลเฉพาะลูปของตัวเอง
Outer for-loop (นับแถว)
r = 0r < nrowr += 1r คี่Inner for-loop (นับคอลัมน์)
c = 0c < ncolc += 1r == cความฝัน vs ความจริงของการ automate ด้วยลูป

ที่มา: xkcd #1319 — “Automation” (CC BY-NC 2.5)
range()
range(START, STOP, STEP)range(START, STOP) — STEP=1range(STOP) — START=0, STEP=1STOPfor
while ได้Nested loop (ลูปซ้อน)
while / for ซ้อนกันได้break / continue
break — ออกจากลูปcontinue — ข้ามไปรอบถัดไป🏠 259201 — Module 7 | ภาควิชาวิศวกรรมคอมพิวเตอร์ คณะวิศวกรรมศาสตร์ มหาวิทยาลัยเชียงใหม่