ข้ามไปยังเนื้อหา

Slicing

Slice notation ของ Python ดึงลำดับย่อยจาก sequence type ใด ๆ — list, tuple, string และ bytes

seq[start : stop : step]
  • start — index ของ element แรกที่รวม (ค่าเริ่มต้น: 0)
  • stop — index ถัดจาก element สุดท้ายที่รวม (ค่าเริ่มต้น: len(seq))
  • step — ช่วงระหว่าง element (ค่าเริ่มต้น: 1)

ส่วนใดก็ตามสามารถละได้ Python จะใส่ค่าเริ่มต้นให้

nums = [10, 20, 30, 40, 50, 60, 70]
nums[:3] # [10, 20, 30] — สามตัวแรก
nums[2:5] # [30, 40, 50] — index 2, 3, 4
nums[::2] # [10, 30, 50, 70] — ทุก element ที่สอง
nums[::-1] # [70, 60, 50, 40, 30, 20, 10] — กลับลำดับ

Python รองรับ negative index: -1 คือ element สุดท้าย, -2 คือรองสุดท้าย และต่อไป

nums = [10, 20, 30, 40, 50, 60, 70]
nums[-1] # 70 — element สุดท้าย
nums[-3:] # [50, 60, 70] — สามตัวสุดท้าย
nums[:-3] # [10, 20, 30, 40] — ทุกอย่างยกเว้นสามตัวสุดท้าย

Negative index ทำให้เข้าถึงส่วนท้ายของ sequence ได้ง่ายโดยไม่ต้องรู้ความยาว

seq[::-1] คือวิธีที่ idiomatic ใน Python เพื่อกลับลำดับ sequence ใด ๆ คืนค่าเป็น object ใหม่ที่กลับลำดับ — ไม่แก้ไข sequence ต้นฉบับ

original = [1, 2, 3, 4, 5]
reversed_copy = original[::-1] # [5, 4, 3, 2, 1]
print(original) # [1, 2, 3, 4, 5] — ไม่เปลี่ยนแปลง

สำหรับ string [::-1] ทำงานเหมือนกัน:

s = 'Hello, World!'
print(s[::-1]) # !dlroW ,olleH

seq[:] (ไม่มี start, stop หรือ step) คืน shallow copy ของ sequence list ใหม่เป็น object ที่ต่างกันแต่แต่ละ element ยังชี้ไปยัง object เดียวกัน

original = [1, 2, 3, 4, 5]
copy = original[:]
copy[0] = 99
print(original) # [1, 2, 3, 4, 5] — ไม่เปลี่ยนแปลง
print(copy) # [99, 2, 3, 4, 5]

สำหรับโครงสร้างซ้อน (list ภายใน list) ใช้ copy.deepcopy() แทนหากต้องการ inner list ที่เป็นอิสระ

เก็บ slice ในตัวแปรด้วย slice(start, stop, step) เพื่อความอ่านง่าย:

HEADER = slice(None, 5)
PAYLOAD = slice(5, -2)
FOOTER = slice(-2, None)
data = b'HDRpayload!FT'
nums = [10, 20, 30, 40, 50, 60, 70]
print('first 3:', nums[:3])
print('last 3:', nums[-3:])
print('middle:', nums[2:5])
print('every other:', nums[::2])
print('reversed:', nums[::-1])
s = 'Hello, World!'
print('first 5:', s[:5])
print('last 6:', s[-6:])
print('every 2nd:', s[::2])
print('reversed:', s[::-1])
original = [1, 2, 3, 4, 5]
copy = original[:]
copy[0] = 99
print('original:', original)
print('copy:', copy)
`nums[2:5]` คืนค่าอะไรสำหรับ `nums = [10, 20, 30, 40, 50, 60, 70]`?
`nums[-3:]` คืนค่าอะไรสำหรับ list เดียวกัน?
Slice expression ใดที่กลับลำดับ sequence?
`original[:]` สร้าง deep copy หรือ shallow copy?