ในบทที่ ๓ ได้แนะนำข้อมูลชนิดต่างๆไปคร่าวๆ แต่ยังไม่ได้กล่าวถึงข้อมูลชนิดกลุ่มซึ่งเป็นรายการที่ประกอบด้วยข้อมูลหลายชนิดมารวมกัน
ข้อมูลลักษณะนั้นมีอยู่หลายชนิดได้แก่ ลิสต์ (list), ทูเพิล (tuple), ดิกชันนารี (dict), เซ็ต (set), เรนจ์ (range) เป็นต้น
ในจำนวนนั้นก็ยังแบ่งเป็นข้อมูลที่มีการเรียงลำดับ และที่ไม่มีการเรียงลำดับ ข้อมูลที่มีการเรียงลำดับจะเรียกว่าเป็นข้อมูลชนิดลำดับ (sequence) ซึ่งได้แก่ ลิสต์, ทูเพิล และเรนจ์
ความจริงแล้วสายอักขระ (str) ก็ถือเป็นข้อมูลชนิดลำดับเช่นกัน ซึ่งก็ได้แนะนำไปพอสมควรแล้ว
ในบทนี้จะมาเรียนรู้เกี่ยวกับพื้นฐานของลิสต์, ทูเพิล และเรนจ์
ลิสต์ ลิสต์คือรายการของข้อมูลซึ่งประกอบไปด้วยข้อมูลหลายตัวมาวางเรียงต่อกันโดยมีลำดับที่แน่นอน ข้อมูลที่เก็บอยู่ในลิสต์จะเป็นชนิดใดก็ได้ และอาจเป็นหลายชนิดปนกันก็ได้
การเขียนลิสต์ทำโดยนำข้อมูลทั้งหมดที่ต้องการให้เป็นสมาชิกมาวางต่อกันแล้วคั่นด้วยจุลภาค
,
จากนั้นก็ครอบทั้งหมดด้วยวงเล็บเหลี่ยม
[ ]
เช่น
list_a = [3, 2, 5, 4, 9] # สร้างลิสต์ของจำนวนเต็ม
list_b = [195.1, 129.3, 201.6, 110.5] # สร้างลิสต์ของจำนวนจริง
Cnidaria = ['กัลปังหา', 'ปะการัง', 'ดอกไม้ทะเล', 'แมงกะพรุน'] # สร้างลิสต์ของสายอักขระ
kpkp = [11111, 999.99, 'กกกกก'] # ข้อมูลหลายชนิดปนกัน
ข้อมูลภายในลิสต์นั้นสามารถที่จะแก้ไขเปลี่ยนแปลงเพิ่มเติมได้ภายหลังจากที่สร้างขึ้นมาแล้ว คุณสมบัติข้อนี้คือจุดที่แตกต่างจากทูเพิล
ทูเพิล คือรายการข้อมูลซึ่งโดยทั่วไปแล้วมีลักษณะเหมือนกับลิสต์ แต่ข้อแตกต่างคือไม่สามารถแก้ไขเปลี่ยนแปลงสมาชิกภายในได้หลังจากที่ถูกสร้างขึ้นมาแล้ว หากอยากแก้ไขมีแต่ต้องสร้างทูเพิลตัวใหม่ขึ้นมาทับ
อย่างไรก็ตามโดยทั่วไปทูเพิลมีข้อดีกว่าลิสต์คือทำงานได้เร็วกว่า ดังนั้นหากมีรายการของข้อมูลที่คิดว่าสร้างขึ้นมาแล้วไม่จำเป็นต้องมีการ แก้ไขเพิ่มเติมอะไรแล้วก็อาจเลือกใช้ทูเพิลแทนลิสต์
การสร้างทูเพิลสามารถทำได้คล้ายลิสต์ เพียงแต่เปลี่ยนจากวงเล็บเหลี่ยมเป็นวงเล็บโค้ง
( )
Mollusca = ('หมึก','ทากเปลือย','หอยฝาเดียว','หอยสองฝา','หอยงวงช้าง','หอยงาช้าง') # สร้างทูเพิลของสายอักขระ
หากทูเพิลมีสมาชิกอยู่เพียงตัวเดียวจะต้องใส่จุลภาพไว้ข้างหลังด้วย
Porifera = ('ฟองน้ำ',)
ทูเพิลกับลิสต์สามารถเปลี่ยนไปมาได้โดยใช้ชื่อคลาสเป็นตัวแปลง เช่น
Cnidaria2 = tuple(Cnidaria) # สร้างทูเพิลขึ้นจากลิสต์ Cnidaria ที่สร้างขึ้นในตัวอย่างข้างต้น
print(Cnidaria2) # ได้ ('กัลปังหา', 'ปะการัง', 'ดอกไม้ทะเล', 'แมงกะพรุน')
หรือเปลี่ยนจากทูเพิลเป็นลิสต์
Echinodermata = ('ดาวทะเล','ดาวเปราะ','เม่นทะเล','ปลิงทะเล','เหรียญทะเล','พลับพลึงทะเล')
print(list(Echinodermata)) # ได้ ['ดาวทะเล', 'ดาวเปราะ', 'เม่นทะเล', 'ปลิงทะเล', 'เหรียญทะเล', 'พลับพลึงทะเล']
เรนจ์ เป็นรายการของข้อมูลตัวเลขจำนวนเต็มที่เรียงกันโดยมีระยะห่างคงที่ เช่น
1,2,3,4,5
การสร้างเรนจ์ทำได้โดยใช้พิมพ์
range()
แล้วใส่อาร์กิวเมนต์ลงไป มีอยู่ ๓ รูปแบบในการสร้างโดยแบ่งตามจำนวนอาร์กิวเมนต์ที่ใช้
นั่นคือ ถ้าใส่อาร์กิวเมนต์ตัวเดียว จะได้ค่าที่ไล่ตั้งแต่
0
โดยบวกทีละ
1
ไปจนถึงค่าก่อนค่านั้น เช่น
r = range(12)
จะได้ค่าไล่เรียงตั้งแต่
0
ถึง
11
แต่เราไม่สามารถเห็นค่าทั้งหมดนั้นได้โดยการแค่ใช้
print
แม้จะพิมพ์
print(r)
ก็จะได้ออกมาเป็น
range(0, 12)
เราสามารถเห็นค่าสมาชิกทั้งหมดของเรนจ์ได้โดยแปลงเป็นลิสต์หรือทูเพิล
print(list(r)) # ได้ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
- ถ้าใส่อาร์กิวเมนต์ ๒ ตัว จะได้ค่าที่ไล่ตั้งแต่ค่าตัวซ้ายบวกไปทีละ
1
ไปจนถึงก่อนค่าตัวขวา เช่น
r = range(129,135)
print(tuple(r)) # ได้ (129, 130, 131, 132, 133, 134)
- ถ้าใส่อาร์กิวเมนต์ ๓ ตัว จะได้ค่าที่ไล่ตั้งแต่ตัวซ้ายและเพิ่มขึ้นเท่ากับค่าของตัวขวาไปเรื่อยๆ ไปจนถึงตัวกลาง เช่น
r = range(1000,2000,100)
print(list(r)) # ได้ [1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900]
อนึ่ง แม้ว่าเรนจ์แปลงเป็นลิสต์แล้วจะได้ค่าเทียบเท่ากับลิสต์ แต่ก็ถือเป็นออบเจ็กต์คนละชนิดกัน ดังนั้นหากเอามาเปรียบเทียบว่าเท่ากันหรือเปล่าก็จะได้ค่าเป็นเท็จ
print(list(range(1,4)) == [1,2,3]) # ได้ True
print(range(1,4) == [1,2,3]) # ได้ False
แท้จริงแล้วเรนจ์นั้นเป็นออบเจ็กต์ในกลุ่มที่เรียกว่า
อิเทอเรเตอร์ (iterator) คือเป็นออบเจ็กต์ที่ไม่ได้เก็บข้อมูลอะไรไว้มากมายแต่เมื่อถูกเรียกใช้มันก็จะสามารถสร้างข้อมูลจำนวนมากขึ้นมาได้
เช่นในกรณีของเรนจ์นั้นจะเก็บแค่อาร์กิวเมนต์ ๓ ตัวคือค่าเริ่มต้น ค่าสุดท้าย แล้วก็ระยะเว้น เพียงเท่านี้เมื่อเรียกใช้มันก็จะให้ค่าตัวเลขที่ไล่เรียงไปทั้งหมดตามที่ต้องการ
***ในไพธอน 2
range
เป็นเพียงฟังก์ชันสำหรับสร้างลิสต์ที่เป็นตัวเลขเรียง ไม่ใช่อิเทอเรเตอร์
>>>
รายละเอียด ความยาวของลิสต์, ทูเพิล และเรนจ์ ลิสต์สามารถมีสมาชิกกี่ตัวก็ได้แล้วแต่จะใส่สมาชิกเข้าไป การหาจำนวนสมาชิกในลิสต์ทำได้โดยใช้ฟังก์ชัน
len
ซึ่งจะคืนค่าความยาว (ซึ่งก็คือจำนวนสมาชิก) ของลิสต์ออกมา
len(['a','e','i','o','u','ä','ö','ü']) # ได้ 8
len(range(1,99,3)) # ได้ 33
chamnuakhi = (1,3,5,7,9,11)
print(len(chamnuakhi)) # ได้ 6
ลิสต์, ทูเพิลและเรนจ์อาจไม่จำเป็นต้องมีสมาชิกอยู่เลยก็ได้ กรณีนี้ความยาวจะเป็น 0
[] # ลิสต์ว่าง
() # ทูเพิลว่าง
range(0, 0) # เรนจ์ว่าง
การเข้าถึงสมาชิกแต่ละตัว ค่าของสมาชิกแต่ละตัวหาได้โดยพิมพ์ชื่อของลิสต์นั้นตามด้วยเลขลำดับของสมาชิก ใส่ครอบด้วยวงเล็บเหลี่ยม
[ ]
โดยที่ตำแหน่งแรกเริ่มนับจาก
0
ไม่ใช่
1
แต่ถ้าหากระบุตัวเลขเกินจำนวนสมาชิกก็จะขัดข้องขึ้นมาทันที
phasa = ['Thai','English','Python','C++','html']
print(phasa[0]) # ได้ 'Thai'
print(phasa[2]) # ได้ 'Python'
print(phasa[5]) # ได้ IndexError: list index out of range
ตัวอย่างนี้สมาชิกมี ๕ ตัว ซึ่งแต่ละตัวชี้ด้วยเลข
0, 1, 2, 3, 4
ดังนั้นถ้าพิมพ์
phasa[5]
จึงเกินขอบเขต
อนึ่ง ระวังไว้ว่าวงเล็บเหลี่ยมตอนที่อ้างอิงถึงสมาชิกกับวงเล็บเหลี่ยมตอนที่สร้างลิสต์ถือเป็นคนละเรื่องกัน ต้องไม่สับสน
เลขที่ใส่อาจเป็นจำนวนติดลบได้เช่นกัน กรณีนี้จะนับลำดับเรียงโดย
-1
คือตัวสุดท้าย แล้วก็ไล่มาเรื่อยๆ จนติดลบสูงสุดคือเท่ากับจำนวนสมาชิกในลิสต์ ซึ่งจะได้ตัวแรก
print(phasa[-1]) # ได้ 'html'
print(phasa[-5]) # ได้ 'Thai'
ค่าใน
[ ]
ต้องเป็นจำนวนเต็มเท่านั้น ถ้าใส่จำนวนจริงหรือสายอักขระเข้ามาก็จะขัดข้องทันที
print(phasa[1.0]) # ได้ TypeError: list indices must be integers or slices, not float
หากต้องการแก้ไขข้อมูลก็สามารถทำได้โดยใช้
=
เพื่อใส่ค่าใหม่ให้ทันที
phasa[3] = 'C#'
phasa[1] = 'Singlish'
phasa = print(phasa) # ได้ ['Thai', 'Singlish', 'Python', 'C#', 'html']
ทูเพิลสามารถเข้าถึงสมาชิกได้ในลักษณะเดียวกับลิสต์ แต่ไม่สามารถแก้
pokemon_red = ('pikachu','fushigibana','nyorobon','kabigon','ptera')
print(pokemon_red[3]) # ได้ 'kabigon'
pokemon_red[0] = 'raichu' # ได้ TypeError: 'tuple' object does not support item assignment
การเข้าถึงสมาชิกทีละหลายตัว สามารถเข้าถึงสมาชิกภายในลำดับทีละหลายตัวได้โดยใช้โคลอน
:
หากใส่ตัวเลขวางไว้หน้า : จะหมายความว่าเอาสมาชิกไล่ตั้งแต่ลำดับของเลขนั้นไปจนถึงท้ายลิสต์
หากใส่ตัวเลขวางไว้หลัง
:
จะหมายความว่าเอาสมาชิกไล่ตั้งแต่
0
ไปจนถึงก่อนหน้าที่จะถึงเลขนั้น
แต่ถ้าใส่เลขทั้งหน้าและหลัง
:
จะหมายความว่าเอาสมาชิกตั้งแต่เลขตัวซ้าย ไปจนถึงก่อนเลขตัวขวา
ตัวอย่างเช่น
pokemon = ['fushigidane','hitokage','zenigame','fushigisou','lizardo','kamel','fushigibana','lizardon','kamex']
print(pokemon[:3]) # ได้ ['fushigidane', 'hitokage', 'zenigame']
print(pokemon[6:]) # ได้ ['fushigibana', 'lizardon', 'kamex']
print(pokemon[3:6]) # ได้ ['fushigisou', 'lizardo', 'kamel']
ให้ระวังว่าสมาชิกในลำดับของตัวเลขทางซ้าย
:
จะถูกรวมอยู่ในผลที่ได้ด้วย ในขณะที่สมาชิกทางขวาของ
:
จะไม่ถูกรวม แต่จะรวมแค่จนถึงก่อนถึงตัวนั้น เช่น
[2:5]
หมายถึงเอาแค่
2,3,4
แต่ไม่ได้เอา
5
อนึ่ง กรณีที่เลขทางซ้ายและขวาต่างกันอยู่
1
จะได้ผลลัพธ์เพียงตัวเดียว เช่น
pokemon[3:4]
จะได้
'fushigisou'
ตัวเดียวเช่นเดียวกับ
pokemon[3]
อย่างไรก็ตามผลที่ได้คือลิสต์
['fushigisou']
ไม่ใช่แค่สายอักขระ
'fushigisou'
เฉยๆ แม้จะมีสมาชิกเพียงตัวเดียวก็ถือว่าเป็นลิสต์ หากจะเข้าถึง
'fushigisou'
ก็ต้องพิมพ์
[0]
ต่อท้ายอีกทีเป็น
pokemon[3:4][0]
กรณีที่มีการใส่
:
ตัวที่สอง แล้วมีเลขต่อท้ายอีกตัว เลขตัวนั้นจะเป็นเลขกำหนดขั้นว่าจะโดดข้ามทีละกี่ตัว
print(pokemon[::3]) # ได้ ['fushigidane', 'fushigisou', 'fushigibana']
print(pokemon[1:8:3]) # ได้ ['hitokage', 'lizardo', 'lizardon']
print(pokemon[2::3]) # ได้ ['zenigame', 'kamel', 'kamex']
สำหรับลิสต์แล้วเราสามารถแก้ข้อมูลลงไปได้เลย โดยจำนวนที่มาแทนไม่จำเป็นต้องเท่ากัน เช่น
pokemon[:6] = ['lugia','houou']
print(pokemon) # ได้ ['lugia', 'houou', 'fushigibana', 'lizardon', 'kamex']
ถ้าใส่เป็นลิสต์ว่างไปก็จะเป็นการลบสมาชิกแถวนั้นออกทั้งหมด
pokemon[:2] = []
print(pokemon) # ได้ ['fushigibana', 'lizardon', 'kamex']
แต่ถ้าเป็นทูเพิลกับเรนจ์จะทำได้แต่ดูค่า แต่ไม่สามารถเปลี่ยนแปลงแก้ไขอะไรได้
การเพิ่มสมาชิกในลิสต์ มีหลายวิธีในการเพิ่มสมาชิกในลิสต์ สำหรับการเพิ่มต่อไปในตำแหน่งท้ายสุดอาจทำได้โดยใช้เมธอด
.append
โดยใส่อาร์กิวเมนต์เป็นตัวที่ต้องการเพิ่มเข้าไป
a = [1,6,44,78,231]
a.append(442)
print(a) # ได้ [1, 6, 44, 78, 231, 442]
แต่หากต้องการเพิ่มตำแหน่งที่ไม่ใช่ท้ายสุดให้ใช้เมธอด
.insert
โดยอาร์กิวเมนต์ตัวแรกเป็นตำแหน่งที่ต้องการแทรกแล้วค่อยตามด้วยสิ่งที่ต้องการแทรก
a.insert(3,49)
print(a) # ได้ [1, 6, 44, 49, 78, 231]
หรืออาจใช้
=
เพื่อแทรกลงไปในลิสต์ตรงช่วงที่ต้องการได้เช่นกัน
a[3:3] = [49]
print(a) # ได้ [1, 6, 44, 49, 78, 231]
หากจะเพิ่มที่ตำแหน่งท้ายก็ใส่เลขตำแหน่งสุดท้ายได้
b = ['ผ','ศ']
b[2:2] = ['ด','ร']
print(b) # ได้ ['ผ', 'ศ', 'ด', 'ร']
อีกวิธีหนึ่งที่อาจใช้ก็คือการสร้างลิสต์ใหม่โดยขยายจากลิสต์เก่า เช่น
c = ['á','à','â','ä']
c = c + ['ã']
c += ['ā']
print(c) # ได้ ['á', 'à', 'â', 'ä', 'ã', 'ā']
เฉพาะวิธีสุดท้ายนี้เท่านั้นที่สามารถใช้กับทูเพิลได้ด้วย เพราะไม่ใช่การแก้ของเก่าแต่เป็นการสร้างขึ้นมาใหม่จากของเก่า
c = ('ó','ò','ô','ö')
c = c + ('õ',)
c += ('ō',)
print(c) # ได้ ('ó', 'ò', 'ô', 'ö', 'õ', 'ō')
การลบสมาชิกออกจากลิสต์ นอกจากจะใช้วิธีการแทนที่ส่วนที่ต้องการลบด้วยลิสต์ว่างแล้ว การลบสมาชิกออกจากลิสต์อาจสามารถทำได้โดยใช้เมธอด
.remove
และ
.pop
เมธอด
.pop
ใช้ลบสมาชิกออกจากลิสต์โดยระบุตำแหน่งของตัวที่ต้องการลบ เช่น
d = ['ú','ù','û','ü','ư','ủ','ũ','ū']
d.pop(4)
print(d) # ได้ ['ú', 'ù', 'û', 'ü', 'ủ', 'ũ', 'ū']
แต่หากไม่ได้ระบุตำแหน่งที่ต้องการลบ ใส่เป็น
.pop()
เฉยๆจะเป็นการลบตัวสุดท้าย
ส่วน
.remove
เป็นคำสั่งลบโดยระบุตัวที่ต้องการลบ
d.remove('ủ')
print(d) # ได้ ['ú', 'ù', 'û', 'ü', 'ũ', 'ū']
แต่หากตัวที่ต้องการลบนั้นมีอยู่หลายตัว จะเป็นการลบแค่ตัวแรกเท่านั้น ตัวที่เหลือจะยังอยู่
dd = ['u','u','a','u']
dd.remove('u')
print(dd) # ได้ ['u', 'a', 'u']
รายการของรายการของข้อมูล สมาชิกของลิสต์หรือทูเพิลอาจประกอบไปด้วยลิสต์หรือทูเพิลซ้อนอยู่ภายในก็ได้ กรณีแบบนี้ก็จะเกิดเป็นลิสต์ซ้อนลิสต์หรือทูเพิลซ้อนทูเพิล ตัวอย่างเช่น
m = [['a','b','c'],['d','e','f'],['g','h','j'],['k','l']]
print(m[1]) # ได้ ['d', 'e', 'f']
print(m[1:3]) # ได้ [['d', 'e', 'f'], ['g', 'h', 'j']]
print(m[3]) # ได้ ['k', 'l']
การเข้าถึงสมาชิกของลิสต์ในลิสต์ทำได้โดยการเขียนวงเล็บเหลี่ยมต่อกันสองตัว เช่น
print(m[1][2]) # ได้ f
print(m[1:3][1]) # ได้ ['g', 'h', 'j']
print(m[3][3]) # ได้ IndexError: list index out of range
ภาพแสดงการเก็บข้อมูลในลิสต์ซ้อนลิสต์
ลิสต์อาจซ้อนเป็นชั้นกี่ชั้นก็ได้ เวลาจะเข้าถึงข้อมูลด้านในก็ต้องใช้วงเล็บเหลี่ยมเขียนต่อกันเป็นจำนวนเท่ากับชั้น
สรุปเนื้อหา
- ข้อมูลชนิดลำดับได้แก่ ลิสต์, ทูเพิล และเรนจ์
- ทั้งหมดมีคุณสมบัติเหมือนกันคือเป็นรายการของข้อมูลซึ่งมีลำดับแน่นอน สามารถเข้าถึงข้อมูลภายในได้โดยใช้เลขดัชนีเป็นตัวชี้
- ลิสต์ต่างจากทูเพิลตรงที่ลิสต์เปลี่ยนแก้ข้อมูลภายในได้แต่ทูเพิลแก้ไม่ได้
อ้างอิง