專項練習 · 8 分鐘閱讀

Python collections 練習:計數、分組與佇列

collections 模組提供一組減少樣板程式碼的小工具。你不需要手寫計數迴圈、缺失鍵判斷或佇列,而是直接選擇行為已經比對問題的容器。

先計數,再查詢

Counter 把可迭代物件轉換成計數。它是字典子類,所以缺失鍵讀取為零,同時仍可使用普通映射方法。most_common 適合快速排序,直接索引適合單次查詢。

from collections import Counter
votes = ["yes", "no", "yes", "yes"]
counts = Counter(votes)
print(counts["yes"])
print(counts.most_common(1))

一次計數,多次查詢

給缺失鍵合理的預設值

defaultdict 在鍵不存在時呼叫工廠函式。使用 list 時可以直接 append,不必先判斷鍵是否存在。工廠必須可呼叫,預設值只在存取該鍵時建立。

from collections import defaultdict
groups = defaultdict(list)
for word in ["ant", "ape", "bee"]:
    groups[word[0]].append(word)
print(dict(groups))

分組時不再判斷鍵

兩端都重要時用 deque

列表在右端操作高效,在左端操作代價較高。deque 支援在兩端快速添加和彈出。佇列可以用 appendleft 和 popleft,需要迴圈移動元素時可以用 rotate。

from collections import deque
queue = deque(["a", "b"])
queue.append("c")
queue.popleft()
print(list(queue))

兩端操作都很快

把計數當作可運算的值

Counter 支援計數相加和相減。比較兩組物品時很方便,但相減會丟棄非正數結果。update 可以從另一個可迭代物件或映射累加計數。

from collections import Counter
first = Counter("aab")
second = Counter("abb")
print(first + second)
print(first - second)

計數也能組合

按需要的操作選擇容器

根據最常執行的操作選擇容器:計數、分組還是兩端存取。如果既不需要預設值也不需要計數,普通 dict 仍然最合適。可讀性來自工具與任務比對,而不是在一個檔案裡用遍所有容器。

from collections import Counter, deque
print(Counter("aba").most_common(1))
print(deque([1, 2, 3]).popleft())

讓容器比對任務

你的練習清單

常見問題

Counter 是字典嗎?

是。Counter 是 dict 的子類,查詢缺失鍵時按零處理。

什麼時候用 defaultdict 而不是 dict.get?

當同一個缺失鍵預設值在迴圈中反覆出現時用 defaultdict。只查一兩次時,dict.get 通常更清楚。

deque 可以索引嗎?

可以,但索引不是使用 deque 的主要理由。兩端頻繁增刪才是它最合適的場景。

練習 collections

12 道題,覆蓋 Counter、defaultdict、deque、分組和容器選擇。

打開練習

繼續閱讀: