# ลิสต์ใน Python (list): เมธอด, slice, การเรียงลำดับ, append, tuple และ set

URL: https://skillaria.top/th/guides/python/python-lists

ลิสต์ (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()` กลับลำดับในลิสต์เดิม และคืนค่า `None`
- `a[::-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: ตั้งแต่มือใหม่ถึงมืออาชีพ"

## FAQ

**ลิสต์ใน 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


---
Source: Skillaria.Top (https://skillaria.top)
