6. 資料結構 - 字典, 集合
字典Dictionary
在資料結構中有一種叫做字典(Dictionary), 在 python 中我們可以簡寫為dict
在程式語言中, 這種結構其實就是類似於雜湊表(Hash table), 這裡就不做討論
這一種資料結構是沒有順序的, 所以他當然不會使用index來查找值
反之, 他所使用的是鍵(Key), dict
透過 Key
來查找值(Value)
假設今天要宣告一個空的dict
, 我們使用{}
,
又或者直接呼叫dict()
函式, 不要帶任何引數
>>> emptyDict = {}
>>> emptyDict
{}
>>> emptyDict = dict()
{}
在dict
的宣告時, 我們用:
來建立起Key
跟Value
的對應,
用,
來區分每一對的Key-Value
因為必須從Key
去查找資料, 所以Key
一定要是唯一的, 並且是不可變的物件
例如 python 的基礎型別(int
, float
, string
, bool
) 以及tuple
接者我們來看看如何宣告一個有資料的dict
>>> fruits = {
... 'apple': 10,
... 'banana': 5,
... 'orange': 8,
... }
>>> fruits
{'apple': 10, 'banana':5, 'orange': 8}
假設電腦回應的結果順序跟範例不一樣是正常的, 因為前面有提到dict
是不在乎順序的
為了可讀性, 我們通常每一對
Key-Value
都宣告一行
新增或修改項目
在dict
中新增或修改項目是相當容易的, 首先他跟前面提到的資料結構一樣用[]
來查找值
>>> fruits['apple']
10
方便的是, dict
可以直接透過這種方式來更改或新增值
>>> fruits['apple'] = 20
>>> fruits
{'apple': 20, 'banana':5, 'orange': 8}
>>> fruits['mango'] = 15
>>> fruits
{'apple': 20, 'banana':5, 'orange': 8, 'mango': 15}
刪除項目
dict
刪除項目的做法也很單純, 其實就是直接使用del
>>> del fruits['mango']
>>> fruits
{'apple': 20, 'banana':5, 'orange': 8}
項目是否存在
既然能使用del
, 當然也可以使用in
,
不過這裡比較特別的是, 直接使用in
時, 只能對Key
作用
>>> 'apple' in fruits
True
>>> 'banana' in fruits
True
>>> 'mango' in fruits
False
>>> 20 in fruits
False
那假設我們直接用取值的方式來看項目是否存在
>>> fruits['apple']
20
>>> fruits['mango']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'mango'
又出現了exception
了, 當要從不存在的Key
去要Value
的時候, 就會有問題
還好dict
有提供一個安全的方法, get
函式也能夠做到跟[]
一樣的事情
>>> fruits.get('apple')
20
>>> fruits.get('mango')
fruits.get('mango')
因為沒有找到東西, 什麼事情都沒發生,
不過我們可以讓他做一個例外處理
>>> fruits.get('mango', 'no mango')
'no mango'
假設找不到東西的情況下, 會回應第二個引數的內容
取回所有的 Key, Value
我們也可以使用keys
取回所有Key
, values
取回所有的 Value
>>> fruits.keys()
['apple', 'banana', 'orange']
>>> fruits.values()
[20, 5, 8]
電腦會使用list
來回應
也可以使用 items
找回所有的 Key-Value
對, 但是是以 tuple
的型態組合
>>> fruits.items()
[('apple', 20), ('banana', 5), ('orange', 8)]
複製dict
等同於 list
的做法, 使用copy
函式, 這裡就不贅述了
>>> copyFruits = fruits.copy()
集合Set
集合(set)是一個很特別的資料結構, 可以想像成沒有value
的dict
,
簡單來說, 這個資料結構一樣沒有順序, 而且裡面的value
都是唯一的
要宣告一個空的集合, 比較不一樣的是, 一定要使用set()
>>> emptySet = set()
>>> emptySet
set()
就連回應的內容都直接回set()
來表示空集合
而一般宣告方式也跟dict
很像, 使用{}
來宣告,
所以當空集合的時候才不是顯示
{}
, 因為會被當成dict
>>> aSet = {1, 3, 5, 7, 9}
>>> aSet
set([1, 3, 5, 7, 9])
項目是否存在
我們一樣能使用in
來做這件事情
>>> 1 in aSet
True
>>> 2 in aSet
False
set運算
相較其他資料結構, 最特別的是他能夠做類似於數學上的集合運算
例如我們可以做交集(intersection)或是聯集(union),
python 分別用 &
與 |
代表, 或者是 intersection()
與 union()
函式
>>> aSet = {1, 3, 5, 7, 9}
>>> bSet = {1, 2, 3, 4, 5}
>>> aSet & bSet
set([1, 3, 5])
>>> aSet.intersection(bSet)
set([1, 3, 5])
>>> aSet | bSet
set([1, 2, 3, 4, 5, 7, 9])
>>> aSet.union(bSet)
set([1, 2, 3, 4, 5, 7, 9])
所以當然也有差集(difference), 可以使用類似於數學的寫法 -
, 或者是呼叫函式difference()
>>> aSet - bSet
set([7, 9])
>>> aSet.difference(bSet)
set([7, 9])
以下其實不太會用到, 所以可以先跳過, 等用到再說吧
其餘還有互斥或(symmetric difference), 使用^
或symmetric_difference()
>>> aSet ^ bSet
set([2, 4, 7, 9])
以及是否為另一個集合的子集合(subset), 使用 <=
或 issubset()
>>> aSet <= bSet
False
真子集(proper subset), 使用 <
>>> aSet < bSet
False
超集合(superset), 使用 >=
>>> aSet >= bSet
False
真超集合(proper superset), 使用 >
>>> aSet > bSet
False