ลิสต์ใน Python (list): เมธอด, slice, การเรียงลำดับ, append, tuple และ set
ลิสต์ (list) ใน Python คือคอลเลกชันที่เรียงลำดับและแก้ไขได้ เขียนในวงเล็บเหลี่ยม เช่น [250, 1200, 99] เพิ่มสมาชิกด้วย append ลบ แทรก และตัดด้วย slice ได้ เมธอด sort เรียงลิสต์ในตัวเองและคืนค่า None ส่วนฟังก์ชัน sorted คืนลิสต์ใหม่ที่เรียงแล้ว
ลิสต์ (list) ใน Python คือชุดของค่าที่เรียงลำดับไว้ เขียนในวงเล็บเหลี่ยม และแก้ไขได้ คุณสามารถเพิ่มสมาชิกท้ายลิสต์ แทรกกลาง ลบ หรือเรียงลำดับได้ เป็นคอลเลกชันที่ใช้บ่อยที่สุดในภาษา บรรทัดในไฟล์ รายจ่ายรายเดือน หรือข้อมูลจาก API ส่วนใหญ่เริ่มต้นจากลิสต์ บทความนี้จะอธิบาย list ใน Python ครบทั้งการสร้าง เมธอด slice การเรียงลำดับ list comprehension และการคัดลอก ปิดท้ายด้วย tuple และ set
ลิสต์ใน Python คืออะไร
ลิสต์เก็บสมาชิกตามลำดับที่คุณกำหนด และเข้าถึงด้วยดัชนีที่เริ่มจากศูนย์ ลิสต์เดียวกันสามารถเก็บค่าต่างชนิดกันได้ แม้ในทางปฏิบัติมักเก็บข้อมูลชนิดเดียวกัน
amounts = [250, 1200, 99]
print(amounts[0]) # 250 — สมาชิกตัวแรก
print(amounts[-1]) # 99 — สมาชิกตัวสุดท้าย
amounts[1] = 1300 # ลิสต์แก้ไขได้
print(len(amounts)) # 3 — ความยาวของลิสต์
ขนาดของลิสต์หาได้ด้วยฟังก์ชัน len() การเข้าถึงดัชนีที่ไม่มีอยู่จริงจะได้ IndexError: list index out of range
การสร้างลิสต์
empty = [] # ลิสต์ว่าง
also_empty = list() # เหมือนกันแต่ใช้ฟังก์ชัน list
nums = [1, 2, 3]
chars = list("abc") # ['a', 'b', 'c']
digits = list(range(5)) # [0, 1, 2, 3, 4]
zeros = [0] * 4 # [0, 0, 0, 0]
ฟังก์ชัน list() แปลงอ็อบเจกต์ใดก็ได้ที่วนซ้ำได้ให้เป็นลิสต์ เช่น สตริง range เซต หรือคีย์ของดิกชันนารี
append และเมธอดอื่นของลิสต์
เมธอด append เพิ่มสมาชิกหนึ่งตัวท้ายลิสต์ เป็นเมธอดที่ใช้บ่อยที่สุดใน Python มันแก้ไขลิสต์เดิมและคืนค่า None
amounts = [250, 1200]
amounts.append(450) # [250, 1200, 450]
amounts.extend([10, 20]) # [250, 1200, 450, 10, 20]
amounts.insert(0, 5) # [5, 250, 1200, 450, 10, 20]
amounts.remove(1200) # ลบค่า 1200 ตัวแรกที่พบ
last = amounts.pop() # 20 — ลบและคืนค่าตัวสุดท้าย
ข้อผิดพลาดที่พบบ่อย: a.append([10, 20]) จะเพิ่มสมาชิกหนึ่งตัว ซึ่งเป็นลิสต์ซ้อนอยู่ข้างใน ไม่ใช่เลขสองตัว หากต้องการเพิ่มหลายสมาชิกให้ใช้ extend
| เมธอด | หน้าที่ |
|---|---|
append(x) | เพิ่ม x ท้ายลิสต์ |
extend(iter) | เพิ่มสมาชิกทั้งหมดของลำดับ |
insert(i, x) | แทรก x ก่อนดัชนี i |
remove(x) | ลบ x ที่พบครั้งแรก (ValueError หากไม่มี) |
pop(i=-1) | ลบและคืนสมาชิกตามดัชนี |
index(x) | ดัชนีของ x ที่พบครั้งแรก |
count(x) | x ปรากฏกี่ครั้ง |
sort() | เรียงลำดับในตัวเอง |
reverse() | กลับลำดับในตัวเอง |
copy() | คัดลอกแบบตื้น (shallow copy) |
clear() | ล้างลิสต์ |
ลบสมาชิกตามดัชนีหรือทั้งช่วงได้ด้วยคำสั่ง del เช่น del a[0] หรือ del a[1:3] ฟังก์ชันในตัวที่ใช้กับลิสต์บ่อยได้แก่ len sum min max sorted reversed enumerate และ zip
Slice ใน Python
Slice ตัดส่วนของลิสต์ตามรูปแบบ a[start:stop:step] คือเริ่มที่ start (รวม) ถึง stop (ไม่รวม) โดยขยับทีละ step ส่วนใดก็ได้สามารถละไว้ได้ และ slice คืนลิสต์ใหม่เสมอ
a = [0, 1, 2, 3, 4, 5]
print(a[1:4]) # [1, 2, 3]
print(a[:2]) # [0, 1] — สองตัวแรก
print(a[-2:]) # [4, 5] — สองตัวสุดท้าย
print(a[::2]) # [0, 2, 4] — ทุกตัวที่สอง
print(a[::-1]) # [5, 4, 3, 2, 1, 0] — กลับลำดับ
print(a[:]) # สำเนาทั้งลิสต์
ต่างจากการเข้าถึงด้วยดัชนี slice ที่เกินขอบเขตจะไม่เกิดข้อผิดพลาด a[10:20] คืน [] ธรรมดา นอกจากนี้ยังกำหนดค่าให้ slice เพื่อแทนที่ช่วงของลิสต์ได้ เช่น a[1:3] = ["x", "y", "z"]
Slice ของสตริง
Slice ทำงานเหมือนกันกับลำดับทุกชนิด รวมถึงสตริงและทูเพิล:
s = "Python 3.15"
print(s[:6]) # Python
print(s[-4:]) # 3.15
print(s[::-1]) # 51.3 nohtyP
สตริงแก้ไขด้วย slice ไม่ได้ เพราะสตริงแก้ไขไม่ได้ การใช้ slice จะสร้างสตริงใหม่ขึ้นมา
เรียงลำดับลิสต์: sort และ sorted
จุดนี้คือส่วนที่มือใหม่สับสนบ่อยที่สุด เมธอด sort สลับตำแหน่งสมาชิกในลิสต์เดิม และคืนค่า None ส่วนฟังก์ชัน sorted ไม่แตะลิสต์เดิม แต่คืนลิสต์ใหม่ที่เรียงแล้ว
amounts = [250, 1200, 99]
amounts.append(450)
print(sorted(amounts)) # [99, 250, 450, 1200] — สำเนาใหม่
print(amounts) # [250, 1200, 99, 450] — ลิสต์เดิมยังอยู่
result = amounts.sort() # เรียงในตัวเอง
print(result, amounts) # None [99, 250, 450, 1200]
นี่คือที่มาของข้อผิดพลาด "ทำไมได้ None": a = a.sort() จะเขียนทับลิสต์ด้วย None ให้เขียนเพียง a.sort() หรือ a = sorted(a)
key และลำดับย้อนกลับ
ทั้งสองแบบรับพารามิเตอร์ key และ reverse โดย key คือฟังก์ชันที่ใช้ผลลัพธ์เป็นตัวเปรียบเทียบสมาชิก
words = ["latte", "Taxi", "subscription"]
print(sorted(words, key=len)) # ['Taxi', 'latte', 'subscription']
print(sorted(words, key=str.lower)) # เรียงโดยไม่สนตัวพิมพ์
print(sorted([3, 1, 2], reverse=True)) # [3, 2, 1]
expenses = [("อาหาร", 650), ("หนัง", 120), ("แท็กซี่", 300)]
expenses.sort(key=lambda e: e[1]) # เรียงตามจำนวนเงิน
การเรียงลำดับของ Python มีความเสถียร (stable) คือสมาชิกที่มีค่า key เท่ากันจะคงลำดับเดิมไว้ ความต่างอีกอย่างคือการใช้งาน sorted รับลำดับใดก็ได้ เช่น สตริง ดิกชันนารี หรือเซต ส่วน sort มีเฉพาะในลิสต์
กลับลำดับลิสต์
มีสามวิธีที่ทำงานต่างกัน:
a.reverse()กลับลำดับในลิสต์เดิม และคืนค่าNonea[::-1]สร้างลิสต์ใหม่ที่กลับลำดับแล้วreversed(a)เป็นตัววนซ้ำแบบขี้เกียจ เหมาะใช้ในลูป:for x in reversed(a):
การวนซ้ำลิสต์
items = ["กาแฟ", "รถไฟฟ้า", "หนัง"]
for item in items:
print(item)
for i, item in enumerate(items, start=1):
print(i, item) # 1 กาแฟ, 2 รถไฟฟ้า, 3 หนัง
print("หนัง" in items) # True — ตรวจว่ามีสมาชิกหรือไม่
อย่าลบสมาชิกออกจากลิสต์ที่กำลังวนซ้ำอยู่ เพราะจะทำให้ข้ามบางสมาชิกไป ให้สร้างลิสต์ใหม่ด้วย comprehension หรือวนซ้ำบนสำเนา a[:]
List comprehension
List comprehension สร้างลิสต์ใหม่ในบรรทัดเดียว ประกอบด้วยนิพจน์ ลูป และเงื่อนไขที่จะใส่หรือไม่ก็ได้
squares = [n * n for n in range(6)] # [0, 1, 4, 9, 16, 25]
big = [a for a in [250, 1200, 99] if a > 200] # [250, 1200]
names = [s.strip() for s in [" สมชาย ", "วิไล"]]
List comprehension มักเร็วกว่าและอ่านง่ายกว่าลูปที่ใช้ append แต่ถ้าตรรกะไม่สามารถอ่านได้ในบรรทัดเดียวอย่างชัดเจน ลูปธรรมดาจะดีกว่า
การรวม การบวก และการลบลิสต์
a = [1, 2, 3]
b = [3, 4]
print(a + b) # [1, 2, 3, 3, 4] — ลิสต์ใหม่
a += b # เหมือน a.extend(b)
print([*a, *b]) # การแตกค่าเป็นลิสต์ใหม่
Python ไม่มีตัวดำเนินการ - สำหรับลบลิสต์ หากต้องการเอาสมาชิกของลิสต์หนึ่งออกจากอีกลิสต์ให้ใช้ comprehension: [x for x in a if x not in set(b)] ส่วนการหาส่วนร่วมของลิสต์สองลิสต์สะดวกที่สุดด้วยเซต: set(a) & set(b) (จะไม่รักษาลำดับและสมาชิกซ้ำ)
ลิสต์ซ้อนและลิสต์สองมิติ
ลิสต์ของลิสต์เป็นวิธีง่าย ๆ ในการเก็บตารางหรือเมทริกซ์:
matrix = [[1, 2, 3], [4, 5, 6]]
print(matrix[1][2]) # 6
grid = [[0] * 3 for _ in range(2)] # ถูกต้อง
bad = [[0] * 3] * 2 # กับดัก: สองแถวชี้ไปยังลิสต์เดียวกัน
bad[0][0] = 9
print(bad) # [[9, 0, 0], [9, 0, 0]]
การแตกค่าลิสต์ (unpacking)
first, second, third = [10, 20, 30]
head, *rest = [1, 2, 3, 4] # head=1, rest=[2, 3, 4]
print(*["a", "b"], sep=", ") # a, b — พิมพ์สมาชิกโดยไม่มีวงเล็บ
หากจำนวนตัวแปรไม่ตรงกับความยาวของลิสต์จะเกิด ValueError เครื่องหมายดอกจันช่วยแก้ปัญหานี้ได้
การคัดลอกลิสต์
b = a ไม่ได้คัดลอกลิสต์ แต่เป็นการตั้งชื่อใหม่ให้อ็อบเจกต์เดียวกัน การแก้ไขผ่าน b จะเห็นใน a ด้วย การคัดลอกอิสระต้องทำอย่างชัดเจน: a.copy() list(a) หรือ a[:] แต่สำหรับข้อมูลซ้อนกัน วิธีนี้ยังไม่พอ ลิสต์ข้างในจะยังใช้ร่วมกัน ต้องใช้ copy.deepcopy(a)
import copy
a = [[1, 2], [3]]
b = a.copy()
b[0].append(99)
print(a) # [[1, 2, 99], [3]] — ลิสต์ซ้อนยังใช้ร่วมกัน
c = copy.deepcopy(a) # สำเนาที่เป็นอิสระทั้งหมด
Tuple: ลิสต์ที่แก้ไขไม่ได้
ทูเพิล (tuple) คล้ายลิสต์ แต่หลังสร้างแล้วแก้ไขไม่ได้ ซึ่งเป็นสัญญาณที่ชัดเจนต่อผู้อ่านว่า นี่คือรายการหนึ่งที่มีฟิลด์คงที่ ไม่ใช่ชุดที่ขยายได้ ทูเพิลแตกค่าได้สะดวก และฟังก์ชันมักใช้ทูเพิลเมื่อต้องคืนค่าหลายตัว
expense = (250, "กาแฟ")
amount, item = expense
expense[0] = 300
# TypeError: 'tuple' object does not support item assignment
ทูเพิลที่ประกอบด้วยค่าที่แก้ไม่ได้สามารถแฮชได้ จึงใช้เป็นคีย์ของดิกชันนารีได้ ทูเพิลที่มีสมาชิกเดียวต้องมีเครื่องหมายจุลภาค: (5,)
Set: เก็บเฉพาะค่าที่ไม่ซ้ำ
เซต (set) เก็บเฉพาะค่าที่ไม่ซ้ำกันและไม่รักษาลำดับ เป็นวิธีที่เร็วที่สุดในการตัดค่าซ้ำและตรวจว่ามีสมาชิกหรือไม่ นอกจากนี้ยังทำการหาส่วนร่วม การรวม และการลบเซตได้
jan = {"อาหาร", "แท็กซี่", "หนัง"}
feb = {"อาหาร", "สมาชิก"}
print(jan & feb) # {'อาหาร'}
print(feb - jan) # {'สมาชิก'}
unique = list(dict.fromkeys([3, 1, 3, 2])) # [3, 1, 2] — ตัดค่าซ้ำและคงลำดับ
empty = set() # {} คือดิกชันนารีว่าง ไม่ใช่เซต
เลือกคอลเลกชันอย่างไร
| งาน | คอลเลกชัน |
|---|---|
| มีลำดับและต้องแก้ไข | list |
| ข้อมูลชุดคงที่ | tuple |
| ค้นหาด้วยคีย์ | dict |
| ไม่ซ้ำ และตรวจว่ามีหรือไม่ | set |
| ค่าตั้งต้นที่แก้ไม่ได้ | frozendict (Python 3.15) |
การตรวจ x in list ไล่ดูสมาชิกทีละตัว ส่วน x in set ทำงานแทบจะทันที หากคุณตรวจการมีอยู่ในลิสต์ขนาดใหญ่หลายครั้งในลูป ให้แปลงลิสต์เป็นเซตก่อน
สรุป
ลิสต์ใน Python คือคอลเลกชันที่เรียงลำดับและแก้ไขได้ append และ extend เพิ่มสมาชิก pop และ remove ลบ slice a[start:stop:step] ตัดส่วนของลิสต์ sort เรียงในตัวเองและคืน None ส่วน sorted คืนลิสต์ใหม่ คัดลอกโดยตั้งใจ ใช้ทูเพิลสำหรับข้อมูลคงที่ และใช้เซตสำหรับค่าที่ไม่ซ้ำ ลิสต์ ทูเพิล ดิกชันนารี และเซตถูกสาธิตแบบลงมือทำในคอร์ส "Python 3.15: ตั้งแต่มือใหม่ถึงมืออาชีพ"
คำถามที่พบบ่อย
ลิสต์ใน Python ต่างจาก array ในภาษาอื่นอย่างไร?
Python ไม่มีอาร์เรย์แบบภาษาอื่นเป็นมาตรฐาน หน้าที่นั้นทำโดยลิสต์ ซึ่งเก็บค่าต่างชนิดได้ สำหรับอาร์เรย์ตัวเลขขนาดกระทัดรัดมีโมดูล array และไลบรารี NumPy
จะหาดัชนีของสมาชิกในลิสต์ได้อย่างไร?
ใช้เมธอด a.index(x) ซึ่งคืนดัชนีของการพบครั้งแรก และจะเกิด ValueError หากไม่มีสมาชิกนั้น จึงควรตรวจ x in a ก่อนเรียกใช้
จะลบค่าซ้ำออกจากลิสต์โดยคงลำดับไว้ได้อย่างไร?
ใช้ list(dict.fromkeys(a)) เพราะดิกชันนารีเก็บคีย์ที่ไม่ซ้ำตามลำดับที่เพิ่มเข้าไป ส่วน list(set(a)) ก็ตัดค่าซ้ำได้ แต่ไม่รักษาลำดับ
จะรวมลิสต์ของสตริงให้เป็นสตริงเดียวได้อย่างไร?
ใช้เมธอด join ของสตริง เช่น ", ".join(["a", "b", "c"]) ได้ "a, b, c" สมาชิกทั้งหมดต้องเป็นสตริง หากเป็นตัวเลขให้แปลงด้วย map(str, a) ก่อน
ลิสต์เก็บค่าต่างชนิดกันได้หรือไม่?
ได้ ลิสต์เดียวกันสามารถมีตัวเลข สตริง ลิสต์อื่น หรืออ็อบเจกต์อื่นปนกันได้ แต่การเรียงลำดับลิสต์แบบนี้โดยไม่มีพารามิเตอร์ key มักเกิดข้อผิดพลาด เพราะเปรียบเทียบตัวเลขกับสตริงไม่ได้ จะได้ TypeError
หัวข้อนี้สอนอย่างละเอียดพร้อมฝึกปฏิบัติในคอร์ส “Python 3.15: от новичка до профи”
ไปที่คอร์ส