Learning Objectives
- 集合(set)的宣告與運算:元素不重複、沒有順序
- 集合相關的方法:add、remove、discard、clear,以及包含關係的判斷
- 聯集、交集、差集、對稱差集的運算子與方法
- 集合生成式(set comprehension)
為什麼需要集合
有些問題只在乎「有沒有」,不在乎順序和次數:一門課有哪些學生、一篇文章用了哪些字、 兩個人都修了哪些課。這時候用集合(set)最直接。
- 集合的元素不會重複:放進重複的值,只會留下一個。
- 集合沒有順序(unordered),所以沒有索引,也不能切片。
- 用大括號
{}括起來、逗號分隔;或用set()把其他資料轉成集合。 - 空集合只能寫
set(),因為{}代表空字典。大括號裡有key: value的是字典,只有一個個值的是集合。 - 集合裡可以放數字、字串、元組等不可變的資料,不能放串列。
集合擅長兩件事:成員測試(x in s)與聯集、交集、差集這類集合運算。
不重複:去除重複的元素
第 2 行放了 5 個字串,但右邊的集合只會有 3 個元素。第 8 行示範最常見的用法:把串列轉成集合來去除重複。
注意:視覺化工具為了方便閱讀,會把集合的元素排序後顯示;真正的集合沒有順序,
print()印出的順序不一定是排好的。需要固定順序時,請用sorted()。
新增與移除元素
remove() 和 discard() 都會移除元素,差別在元素不存在時:remove() 引發 KeyError,discard() 安靜地什麼都不做。
想一想:集合的特性
下面的程式會印出什麼?
s = set([3, 1, 3, 2, 1])
s.add(2)
print(len(s))
下面的程式會印出什麼?
a = {}
b = set()
print(type(a).__name__, type(b).__name__)
s = {1, 2, 3} 之後執行 s.remove(5),會發生什麼事?
集合運算對照表
| 運算子 | 方法 | 名稱 | {1, 2, 3} 與 {2, 3, 4} |
|---|---|---|---|
a | b |
a.union(b) |
聯集(union) | {1, 2, 3, 4} |
a & b |
a.intersection(b) |
交集(intersection) | {2, 3} |
a - b |
a.difference(b) |
差集(difference) | {1} |
a ^ b |
a.symmetric_difference(b) |
對稱差集 | {1, 4} |
a <= b |
a.issubset(b) |
a 包含於 b(子集合) | False |
a >= b |
a.issuperset(b) |
a 包含 b(超集合) | False |
a.isdisjoint(b) |
兩者沒有交集 | False |
< 與 > 是「真子集」「真超集合」:兩個集合相等時為 False。
每個運算都有一個「更新」版本,會直接修改 a:a |= b(update)、a &= b(intersection_update)、
a -= b(difference_update)、a ^= b(symmetric_difference_update)。
聯集、交集、差集、對稱差集
每一行同時用運算子和方法算一次,結果相同。看第 7 行:print() 印出 {8, 6, 7},順序和大小無關,這正是「集合沒有順序」的表現。
包含關係與更新版方法
前幾行只回答 True 或 False,不會改變集合;第 8 行和第 10 行的 &=、|= 則會直接修改 s1,看右邊的物件如何變化。
集合生成式
寫法和串列生成式一樣,只是外面換成大括號;產生的結果會自動去除重複。
追蹤集合運算
下面的程式會印出什麼?
a = {1, 2, 3, 4}
b = {3, 4, 5}
print(sorted(a - b), sorted(a ^ b))
下面的程式會印出什麼?
s = {n % 3 for n in range(10)}
print(len(s))
實作:比較兩人的修課清單
alice 與 bob 是兩位同學的修課清單(alice 不小心重複登記了一門)。請用集合運算完成三個 TODO:印出兩人都修的課、只有 alice 修的課(兩者都排序後印出),以及兩人總共修了幾門不同的課。
重點精華回顧
- 集合(set)的元素不重複、沒有順序,所以不能用索引或切片;常用來去除重複與做成員測試。
- 空集合要寫
set();{}是空字典。集合裡不能放串列。 - 新增
add();移除remove()(找不到會 KeyError)、discard()(找不到不出錯)、clear()(全部清空)。 - 聯集
|、交集&、差集-(有方向性)、對稱差集^,各有對應的方法;&=、|=等會直接修改集合。 - 子集合
<=/issubset,超集合>=/issuperset,沒有交集isdisjoint。 - 集合生成式:
{運算式 for 變數 in 可走訪物件 if 條件}。 - 需要固定順序時用
sorted();視覺化工具顯示的排序只是為了方便閱讀。