ดิกชันนารีเป็นวัตถุที่เก็บค่าข้อมูลหลายๆตัวเช่นเดียวกับลิสต์และทูเพิล แต่จะต่างกันตรงที่ต้องประกอบไปด้วย ๒ ส่วน คือ
คีย์ (key) กับ
ค่า (value) อยู่ด้วยกันเหมือนเป็นคู่อันดับ
ลิสต์และทูเพิลจะใช้เลขดัชนีเป็นตัวชี้ถึงค่าภายในลำดับ แต่ว่าในดิกชันนารีจะใช้คีย์แทน
คีย์นั้นเหมือนเป็นสิ่งที่มาใช้แทนเลขดัชนีในลิสต์หรือทูเพิล คือแทนที่จะใช้ตัวเลขเพื่อชี้สมาชิกก็เปลี่ยนมาใช้คีย์ซึ่งเป็นอะไรก็ได้ที่กำหนดขึ้นเอง
การสร้างและเข้าถึงข้อมูลในดิกชันนารี ดิกชันนารีสามารถสร้างได้โดยใช้วงเล็บปีกกาเช่นเดียวกับเซ็ต แต่ภายในใส่สมาชิกเป็นคู่ๆโดยแต่ละคู่ใส่คีย์ทางซ้ายแล้วคั่นด้วยโคลอน
:
แล้วตามด้วยค่า จากนั้นก็คั่นด้วยจุลภาค
,
แล้วตามด้วยคู่ถัดไป
ตัวอย่าง ดิกชันนารีที่เก็บข้อมูลตึกสูงในไทย
tueksung = {'มหานคร': 313, 'ใบหยก 2': 304, 'อมันตา ลุมพินี': 212,
'อื้อจือเหลียง': 160, 'จัตุรัสจามจุรี': 157, 'ใบหยก 1': 151}
เวลาต้องการเข้าถึงข้อมูลก็ใช้ชื่อดิกชันนารีตามด้วย
[ ]
ซึ่งใส่ชื่อคีย์
print(tueksung['จัตุรัสจามจุรี']) # ได้ 157
print(tueksung['ใบหยก 2']) # ได้ 304
ดิกชันนารีไม่สามารถใช้ตัวเลขเพื่อระบุสมาชิกโดยอาศัยลำดับได้อย่างในลิสต์ ต้องใช้คีย์ตามที่ใส่เข้าไปเท่านั้น
print(tueksung[1]) # ได้ KeyError: 1
ทั้งคีย์และค่าจะเป็นข้อมูลชนิดไหนก็ได้ อาจเป็นตัวเลขก็ได้ เช่น ดิกชันนารีที่เก็บชื่อของโปเกมอน
pokemon = {151: 'mew',
152: 'chicorita', 153: 'bayleaf',154: 'meganium',
155: 'hinoarashi', 156: 'magmarashi',157: 'bakphoon',
158: 'waninoko',159: 'alligates', 160: 'ordile'}
print(pokemon[151]) # ได้ mew
กรณีที่ใช้คีย์เป็นตัวเลขจำนวนเต็มแบบนี้ดูเผินๆอาจดูคล้ายกับลิสต์หรือทูเพิล แต่ต่างกันตรงที่ตัวเลขที่ใส่ต้องเป็นเลขที่มีอยู่ในคีย์เท่านั้นและไม่จำเป็นต้องไล่จาก
0
การซ้ำกันของคีย์และค่า ภายในดิกชันนารีหนึ่งๆ ค่าอาจจะซ้ำกันได้ แต่คีย์จะซ้ำกันไม่ได้
khanaen = {'ฟิสิกส์':97,'ฟิสิกส์':91,'เคมี':96,'คณิตศาสตร์':87}
print(khanaen) # ได้ {'ฟิสิกส์': 91, 'เคมี': 96, 'คณิตศาสตร์': 87}
จะเห็นว่าใส่ค่าซ้ำลงไปแต่สุดท้ายก็เหลือแค่ตัวเดียว
ทั้งนี้เพราะว่าคีย์เป็นสิ่งที่ต้องใช้อ้างอิงเพื่อชี้ถึงค่าในดิกชันนารี จึงไม่สามารถซ้ำกันได้ เช่นเดียวกับฟังก์ชันทางคณิตศาสตร์ที่โดเมนต้องไม่ซ้ำ ถ้าซ้ำกันละก็พอจะเรียกหาค่าก็จะเกิดความคลุมเครือไม่รู้จะเรียกตัวไหน
ในขณะที่ค่านั้นต่อให้ใส่ซ้ำกันจะไม่มีปัญหาอะไร
khanaen = {'ฟิสิกส์ 1':97,'ฟิสิกส์ 2':91,'เคมี 1':91,'เคมี 2':97}
print(khanaen) # ได้ {'ฟิสิกส์ 1': 97, 'ฟิสิกส์ 2': 91, 'เคมี 1': 91, 'เคมี 2': 97}
ในที่นี้ค่าของ
ฟิสิกส์ 1
ซ้ำกับ
เคมี 2
และ
เคมี 1
ซ้ำกับ
ฟิสิกส์ 2
จะเห็นว่าสามารถซ้ำกันได้
keys, values และ items รายการคีย์ทั้งหมดสามารถแสดงได้โดยเมธอด
.keys
ตัวอย่าง ดิกชันนารีแสดงรายชื่อเมืองเอก (เรียกว่าเสิ่งฮุ่ย (shěnghuì, 省会) ในภาษาจีน) ของมณฑลในจีน
shenghui = {'กวางตุ้ง': 'กว่างโจว','เจ้อเจียง': 'หางโจว',
'เหลียวหนิง': 'เสิ่นหยาง','เหอเป่ย์': 'สือเจียจวาง',
'เหอหนาน': 'เจิ้งโจว','ฝูเจี้ยน': 'ฝูโจว',
'ทิเบต': 'ลาซ่า','ซินเจียง': 'อูหลู่มู่ฉี'}
print(shenghui.keys())
ผลที่ได้
dict_keys(['กวางตุ้ง', 'เจ้อเจียง', 'เหลียวหนิง', 'เหอเป่ย์', 'เหอหนาน', 'ฝูเจี้ยน', 'ทิเบต', 'ซินเจียง'])
ข้อมูลที่ได้นี้เป็นชนิด
dict_keys
ซึ่งถือเป็นคลาสเฉพาะคลาสนึง ไม่สามารถเปลี่ยนแปลงแก้ไขค่าในนี้ได้เช่นเดียวกับทูเพิล
ไม่สามารถใช้ตัวเลขชี้ถึงค่าข้างในได้ แต่สามารถใช้
in
เพื่อตรวจดูสมาชิกข้างในได้ สามารถแปลงเป็นลิสต์หรือทูเพิล หรือใช้
.join
เพื่อเชื่อมกันได้
'ไต้หวัน' in shenghui.keys() # ได้ False
'ทิเบต' in shenghui.keys() # ได้ True
{'เหอหนาน','เหอเป่ย์'}.issubset(shenghui.keys()) # ได้ True
{'เหอหนาน','เหอเป่ย์','หูหนาน','หูเป่ย์'}.intersection( shenghui.keys()) # ได้ {'เหอหนาน', 'เหอเป่ย์'}
print(tuple(shenghui.keys())) # ได้ ('กวางตุ้ง', 'เจ้อเจียง', 'เหลียวหนิง', 'เหอเป่ย์', 'เหอหนาน', 'ฝูเจี้ยน', 'ทิเบต', 'ซินเจียง')
print('|'.join(shenghui.keys())) # ได้ กวางตุ้ง|เจ้อเจียง|เหลียวหนิง|เหอเป่ย์|เหอหนาน|ฝูเจี้ยน|ทิเบต|ซินเจียง
ส่วนค่าในดิกชันนารีสามารถแสดงทั้งหมดโดยเมธอด
.values
print(shenghui.values())
จะได้ออกมาเป็นข้อมูลชนิด
dict_values
ซึ่งก็มีคุณสมบัติเหมือนกับ
dict_keys
dict_values(['กว่างโจว', 'หางโจว', 'เสิ่นหยาง', 'สือเจียจวาง', 'เจิ้งโจว', 'ฝูโจว', 'ลาซ่า', 'อูหลู่มู่ฉี'])
และถ้าต้องการให้แสดงคีย์กับค่าคู่กันในรูปของทูเพิลให้ใช้เมธอด
.items
print(shenghui.items())
จะได้ข้อมูลชนิด
dict_items
dict_items([('กวางตุ้ง', 'กว่างโจว'), ('เจ้อเจียง', 'หางโจว'), ('เหลียวหนิง', 'เสิ่นหยาง'), ('เหอเป่ย์', 'สือเจียจวาง'), ('เหอหนาน', 'เจิ้งโจว'), ('ฝูเจี้ยน', 'ฝูโจว'), ('ทิเบต', 'ลาซ่า'), ('ซินเจียง', 'อูหลู่มู่ฉี')])
***ในไพธอน 2 เมธอด
.keys
,
.values
และ
.items
จะได้ผลเป็นลิสต์ แทนที่จะได้เป็นคลาสเฉพาะ
>>> รายละเอียด การใช้ for คู่กับดิกชันนารี เมื่อใช้
for
กับดิกชันนารี ตัวแปรจะไล่ตามคีย์ ไม่ใช่ค่า
for s in shenghui:
print(s,end=' ') # ได้ กวางตุ้ง เจ้อเจียง เหลียวหนิง เหอเป่ย์ เหอหนาน ฝูเจี้ยน ทิเบต ซินเจียง
แต่ก็สามารถเข้าถึงค่าได้ทันทีโดยใส่คีย์ใน
[ ]
for s in shenghui:
print(shenghui[s],end=' ') # ได้ กว่างโจว หางโจว เสิ่นหยาง สือเจียจวาง เจิ้งโจว ฝูโจว ลาซ่า อูหลู่มู่ฉี
หรือใช้เมธอด
.values
ก็สามารถไล่ตามค่าได้
for v in shenghui.values():
print(v,end=' ') # ได้ กว่างโจว หางโจว เสิ่นหยาง สือเจียจวาง เจิ้งโจว ฝูโจว ลาซ่า อูหลู่มู่ฉี
หากจะใช้ทั้งคีย์และค่าก็อาจใช้เมธอด
.items
for v in shenghui.items():
print(v[0],v[1],sep='>',end=' ') # กวางตุ้ง>กว่างโจว เจ้อเจียง>หางโจว เหลียวหนิง>เสิ่นหยาง เหอเป่ย์>สือเจียจวาง เหอหนาน>เจิ้งโจว ฝูเจี้ยน>ฝูโจว ทิเบต>ลาซ่า ซินเจียง>อูหลู่มู่ฉี
การเพิ่มข้อมูลและแก้ไขดิกชันนารี การเพิ่มเติมข้อมูลสามารถทำได้โดยใช้
=
เพื่อป้อนค่าใหม่ลงไปได้เลย
ตัวอย่าง พื้นที่ของจังหวัดในไทย
phuenthi = {'นครราชสีมา': 20494, 'เชียงใหม่': 20107,
'กาญจนบุรี': 19483, 'ตาก': 16407,
'อุบลราชธานี': 15774, 'สุราษฎร์ธานี': 12891}
phuenthi['ชัยภูมิ'] = 12778
phuenthi['แม่ฮ่องสอน'] = 12681
print(phuenthi) # ได้ {'นครราชสีมา': 20494, 'เชียงใหม่': 20107, 'กาญจนบุรี': 19483, 'ตาก': 16407, 'อุบลราชธานี': 15774, 'สุราษฎร์ธานี': 12891, 'ชัยภูมิ': 12778, 'แม่ฮ่องสอน': 12681}
หรืออาจใช้เมธอด
.update
เพื่อรับเอาข้อมูลจากดิกชันนารีอื่นมาก็ได้
phuenthi.update({'เพชรบูรณ์': 12668, 'ลำปาง': 12534})
print(phuenthi) # ได้ {'นครราชสีมา': 20494, 'เชียงใหม่': 20107, 'กาญจนบุรี': 19483, 'ตาก': 16407, 'อุบลราชธานี': 15774, 'สุราษฎร์ธานี': 12891, 'ชัยภูมิ': 12778, 'แม่ฮ่องสอน': 12681, 'เพชรบูรณ์': 12668, 'ลำปาง': 12534}
ในการใช้
=
นั้นจะเป็นการเพิ่มข้อมูลก็ต่อเมื่อคีย์ที่ใส่ไปนั้นไม่มีอยู่เดิม แต่หากคีย์ที่ใส่ไปนั้นมีอยู่ก่อนแล้วจะเป็นการแก้ค่าเขียนทับลงไปใหม่แทน
ตัวอย่างการประยุกต์ใช้ ลองเขียนโปรแกรมสำหรับนับจำนวนตัวอักษรแต่ละตัวที่มีอยู่ในสายอักขระ
r = "Si schiudono i boccioli color di rosa. L'ostinato inverno ha annunciato la propria fine." # สายอักขระที่ต้องการวิเคราะห์
nap = {} # สร้างดิกชันนารีสำหรับเก็บค่าจำนวนของแต่ละตัวอักษร
for s in r.lower(): #เปลี่ยนให้เป็นตัวพิมพ์เล็กเพื่อจะนับรวมพิมพ์ใหญ่พิมพ์เล็กด้วยกัน
if(s<'a' or s>'z'): continue # เอาเฉพาะที่เป็นอักษรโรมัน a ถึง z ถ้าเจอสัญลักษณ์หรือช่องว่างให้ข้าม
if(s not in nap): # ถ้ายังไม่มีอยู่ในดิกชันนารี ให้ป้อนค่าใหม่โดยเริ่มนับ 1
nap[s] = 1
else: # ถ้ามีอยู่ในดิกชันนารีแล้ว ให้แก้ค่าโดยบวกเพิ่มอีก 1
nap[s] += 1
print(nap)
(
ที่มามาจากเนื้อเพลง)
ผลที่ได้
{'s': 4, 'i': 11, 'c': 5, 'h': 2, 'u': 2, 'd': 2, 'o': 12, 'n': 8, 'b': 1, 'l': 4, 'r': 5, 'a': 7, 't': 3, 'v': 1, 'e': 2, 'p': 2, 'f': 1}
หากต้องการให้แสดงผลโดยเรียงตามลำดับอักษรก็ใช้
sorted
for q in sorted(nap):
print('%s: %d'%(q,nap[q]))
หรือถ้าจะให้เรียงตามลำดับที่ปรากฏก็
for q in sorted(nap, key=r.lower().index):
print('%s: %d'%(q,nap[q]))
การใช้ for สร้างดิกชันนารี เช่นเดียวกับลิสต์ ดิกชันนารีก็สามารถสร้างขึ้นจาก
for
ได้
ตัวอย่าง ลองใช้ดิกชันนารีเพื่อสร้างฟังก์ชันทางคณิตศาสตร์ขึ้นมา
f = {x:3*x+2 for x in range(100)} # สร้างฟังก์ชัน 3x+2 ที่มีโดเมนเป็นจำนวนเต็ม 0 ถึง 99
print('f(3)=%d'%f[3]) # ได้ f(3)=11
print('f(23)=%d'%f[23]) # ได้ f(23)=71
print('f(99)=%d'%f[99]) # ได้ f(99)=299
ซึ่งการเขียนแบบนี้จะมีค่าเท่ากับการใช้
for
เพื่อวนเพิ่มค่าไปทีละค่า
f = {} # สร้างดิกชันนารีเปล่าขึ้นมาก่อน
for x in range(100):
f[x] = 3*x+2 # ใส่เพิ่มไปทีละค่า
การลบข้อมูลในดิกชันนารี สามารถลบทีละตัวได้โดยใช้เมธอด
.pop
แล้วระบุคีย์ที่ต้องการลบ
ตัวอย่าง ดิกชันนารีที่เก็บรหัสนักศึกษาและคะแนนวิชาภาษาไพธอนเบื้องต้น 1
python1 = {5966208114: 54, 5966100309: 59, 5966117558: 49,
5966209223: 62, 5966195674: 48, 5966119902: 43}
สมมุติว่ามีนักศึกษาถอนวิชานี้ไปคนนึงเลยต้องลบข้อมูลออก
python1.pop(5966119902)
print(python1) # ได้ {5966208114: 54, 5966100309: 59, 5966117558: 49, 5966209223: 62, 5966195674: 48}
หรืออาจลบโดยใช้คำสั่ง
del
ก็ได้
del ชื่อดิกชันนารี[คีย์ที่ต้องการลบ]
เช่น สมมุติว่านักศึกษาอีกคนก็ถอนวิชานี้
del python1[5966195674]
print(python1) # ได้ {5966208114: 54, 5966100309: 59, 5966117558: 49, 5966209223: 62}
หากต้องการลบทั้งหมดให้ใช้เมธอด
.clear
สมมุติว่านักศึกษาคนอื่นๆก็พากันถอนวิชานี้ออกหมด
python1.clear()
print(python1) # ได้ {}
ถ้าจะลบทั้งดิกชันนารีออกก็ใช้คำสั่ง
del
ตามด้วยชื่อดิกชันนารีโดยไม่ต้องใส่คีย์
สมมุติว่าพอคนถอนไปหมด อาจารย์ก็ลบข้อมูลของวิชานี้ทิ้งเสียเลย
del python1
print(python1) # NameError: name 'python1' is not defined
คีย์หรือค่ามากกว่าหนึ่งตัว บางครั้งค่าที่ต้องการอาจไม่ได้มีแค่ค่าเดียวแต่ต้องการเก็บสองค่าขึ้นไป กรณีแบบนี้สามารถใช้ค่าเป็นลิสต์หรือทูเพิลได้
ตัวอย่างเช่น บันทึกการเดินหมากในเกมโกะซึ่งตารางมีขนาด 19×19 แต่ละช่องแทนด้วยพิกัดในแกน x และ y
goban = {} # สร้างดิกเปล่า แทนตารางโกะเปล่า
goban['ดำ1'] = [16,4] # ฝ่ายดำลงหมากตาที่ 1
goban['ขาว1'] = [4,4]
goban['ดำ2'] = [16,16]
goban['ขาว2'] = [4,17]
goban['ดำ3'] = [3,15]
print(goban)
ผลหลังเดินไป ๕ ตา
{'ดำ1': [16, 4], 'ขาว1': [4, 4], 'ดำ2': [16, 16], 'ขาว2': [4, 17], 'ดำ3': [3, 15]}
ที่มาของหมากกระดานนี้ ศึก Google AlphaGo ปะทะ ฝานฮุย (樊麾)
https://www.youtube.com/watch?v=d9bXaLUPe9I กรณีที่ต้องการคีย์สองตัวขึ้นไปก็สามารถทำได้เช่นกัน เพียงแต่คีย์ไม่สามารถใช้ลิสต์ได้ ต้องใช้ทูเพิลเท่านั้น
เช่น ตัวอย่างที่แล้ว คราวนี้ใช้ตำแหน่งบนตารางเป็นคีย์
goban = {} # สร้างดิกเปล่า แทนตารางโกะเปล่า
goban[(16,4)] = 'ดำ1' # ฝ่ายดำลงหมากตาที่ 1
goban[(4,4)] = 'ขาว1'
goban[(16,16)] = 'ดำ2'
goban[(4,17)] = 'ขาว2'
goban[(3,15)] = 'ดำ3'
print(goban)
ผลหลังเดินไป ๕ ตา
{(16, 4): 'ดำ1', (4, 4): 'ขาว1', (16, 16): 'ดำ2', (4, 17): 'ขาว2', (3, 15): 'ดำ3'}
กรณีนี้จะสะดวกเวลาที่จะค้นว่าตำแหน่งไหนมีการลงหมากไปหรือยังและเป็นหมากอะไรที่ลงไว้ เช่น
x,y = int(input()),int(input()) # ป้อนค่าตำแหน่ง
if((x,y) in goban.keys()):
print(goban[(x,y)]) # ถ้ามีหมากอยู่ก็จะบอกว่าเป็นหมากอะไร
else:
print('ว่างเปล่า') # ถ้าไม่มีก็จะบอกว่าว่างเปล่า
ดิกชันนารีซ้อนดิกชันนารี ค่าภายในดิกชันนารีนอกจากจะใช้ทูเพิลหรือลิสต์ได้แล้วก็ยังสามารถใช้เป็นดิกชัน นารีย่อยข้างในได้อีกด้วย พอซ้อนกันหลายชั้นพอเรียกใช้ก็ต้องใส่
[ ]
ซึ่งมีคีย์ใส่อยู่ซ้อนกัน
ตัวอย่าง ลองสร้างดิกชันนารีเก็บข้อมูลของโปเกมอนจำนวน ๔ ตัว แต่ละตัวใช้ชื่อเป็นคีย์ พอค้นแล้วจะได้ค่าซึ่งเป็นดิกชันนารีที่ประกอบด้วย หมายเลข, ส่วนสูง, น้ำหนัก, และ ชนิด
khomun = {'ฟุชิงิดาเนะ': {'หมายเลข': '001','ส่วนสูง': 0.7,'น้ำหนัก': 6.9,'ชนิด':['พืช','พิษ']},
'ฮิโตคาเงะ': {'หมายเลข': '004','ส่วนสูง': 0.6,'น้ำหนัก': 8.5,'ชนิด':['ไฟ']},
'เซนิงาเมะ': {'หมายเลข': '007','ส่วนสูง': 0.5,'น้ำหนัก': 9.0,'ชนิด':['น้ำ']},
'พีคาชู': {'หมายเลข': '025','ส่วนสูง': 0.4,'น้ำหนัก': 6.0,'ชนิด':['ไฟฟ้า']}}
เวลาเข้าถึงค่าภายในก็ เช่น
print(khomun['พีคาชู']['น้ำหนัก']) # ได้ 6.0
print(khomun['ฟุชิงิดาเนะ']['ชนิด']) # ได้ ['พืช', 'พิษ']
print(khomun['ฮิโตคาเงะ']['หมายเลข']) # ได้ 004
สามารถใช้
for
เพื่อแสดงค่าทั้งหมด
for pk in sorted(khomun):
print('===='+pk+'====') # แสดงชื่อ
for s in khomun[pk]:
if(s!='ชนิด'): print(s+': %s'%khomun[pk][s]) # แสดงหมายเลข, น้ำหนัก, ส่วนสูง
else: print(s+': '+' + '.join(khomun[pk][s])) # แสดงชนิด
ผลลัพธ์
====พีคาชู====
หมายเลข: 025
ส่วนสูง: 0.4
น้ำหนัก: 6.0
ชนิด: ไฟฟ้า
====ฟุชิงิดาเนะ====
หมายเลข: 001
ส่วนสูง: 0.7
น้ำหนัก: 6.9
ชนิด: พืช + พิษ
====ฮิโตคาเงะ====
หมายเลข: 004
ส่วนสูง: 0.6
น้ำหนัก: 8.5
ชนิด: ไฟ
====เซนิงาเมะ====
หมายเลข: 007
ส่วนสูง: 0.5
น้ำหนัก: 9.0
ชนิด: น้ำ
สรุปเนื้อหา ดิกชันนารีเป็นข้อมูลอีกประเภทหนึ่งที่สามารถนำมาประยุกต์ใช้งานได้มากเช่น เดียวกับลิสต์, ทูเพิล และเซ็ต หากแยกใช้ข้อมูลแต่ละอย่างตามความเหมาะสมของงานแล้วก็จะสามารถทำงานอะไร ต่างๆได้อย่างมีประสิทธิภาพ
อ้างอิง