Python มีหลายวิธีสร้าง 2D lists/arrays แต่ต้องรู้ความแตกต่าง เพราะอาจสร้างบั๊กที่ยากต่อการติดตาม
ตัวอย่างโค้ด
❌ วิธีผิด: ใช้ * ซ้อนกัน (Shallow Copy)
rows, cols = (5, 5)
arr = [[0] * cols] * rows
# เปลี่ยนแปลง arr[0][0] = 1
arr[0][0] = 1
for row in arr:
print(row)
✅ วิธีถูกต้อง: ใช้ List Comprehension
rows, cols = (5, 5)
arr = [[0 for i in range(cols)] for j in range(rows)]
arr[0][0] = 1
for row in arr:
print(row)
ผลลัพธ์
# วิธีผิด - ทุกแถวเปลี่ยนไปพร้อมกัน!
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
# วิธีถูกต้อง - เฉพาะแถวแรกเปลี่ยน
[1, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
ทำไมวิธีแรกจึงผิด?
# [[0] * cols] * rows
# ขั้นตอน:
# 1. [0] * cols → สร้างลิสต์ [0, 0, 0, 0, 0] (1 ออบเจ็กต์)
# 2. [...] * rows → คัดลอก reference ของลิสต์เดียวกัน 5 ครั้ง
# ผลลัพธ์: 5 reference ชี้ไปที่ลิสต์เดียวกัน!
# ตรวจสอบด้วย id()
arr = [[0] * 3] * 3
print(id(arr[0]), id(arr[1]), id(arr[2])) # เลข id เหมือนกันทั้ง 3!
วิธีสร้าง 2D List ที่ถูกต้อง
1. List Comprehension (แนะนำ)
rows, cols = 5, 5
arr = [[0 for _ in range(cols)] for _ in range(rows)]
# หรือ
arr = [[0] * cols for _ in range(rows)] # [0]*cols สร้างลิสต์ใหม่ทุกครั้ง
2. ใช้ NumPy (แนะนำสำหรับงานคำนวณ)
import numpy as np
arr = np.zeros((5, 5), dtype=int)
arr[0, 0] = 1
print(arr)
3. ใช้ copy.deepcopy() ถ้าต้องคัดลอก 2D list ที่มีอยู่
import copy
original = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(original)
สรุป
- ❌
[[0]*cols]*rows- สร้าง reference ซ้ำ ผิด! - ✅
[[0]*cols for _ in range(rows)]- สร้างลิสต์ใหม่ทุกแถว ถูกต้อง! - ✅
np.zeros((rows, cols))- ใช้ NumPy สำหรับงานตัวเลข - ✅
copy.deepcopy()- คัดลอกลึกสำหรับ nested structures