集合(Set)#

集合(Set)是 無序不重複 的元素集,類似數學中的集合概念。最常見的用途是去除重複元素,以及進行聯集、交集等集合運算:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 建立集合
s1 = {1, 2, 3, 4, 5}
s2 = {"apple", "banana", "cherry"}

# 重複元素會自動去除
s3 = {1, 2, 2, 3, 3, 3}
print(s3)  # {1, 2, 3}(順序不保證)

# 空集合必須用 set()(因為 {} 是空字典)
empty_set = set()
print(type(empty_set))   # <class 'set'>
print(type({}))          # <class 'dict'>

# 從串列建立集合(去重)
nums = [1, 2, 2, 3, 3, 3, 4]
unique = set(nums)
print(unique)  # {1, 2, 3, 4}

新增與刪除#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
s = {1, 2, 3}

# add():新增單一元素
s.add(4)
print(s)  # {1, 2, 3, 4}

# update():新增多個元素
s.update([5, 6])
print(s)  # {1, 2, 3, 4, 5, 6}

# discard():刪除,元素不存在也不報錯
s.discard(6)
s.discard(99)  # 不報錯
print(s)  # {1, 2, 3, 4, 5}

# remove():刪除,元素不存在會報 KeyError
s.remove(5)
print(s)  # {1, 2, 3, 4}

# pop():隨機移除並回傳一個元素
item = s.pop()
print(item)  # 不確定是哪一個

# clear():清空
s.clear()
print(s)  # set()

查詢#

1
2
3
4
5
6
7
8
s = {1, 2, 3, 4, 5}

# 是否存在
print(3 in s)     # True
print(9 in s)     # False

# 長度
print(len(s))     # 5

集合的 in 操作比串列快得多,時間複雜度為 O(1)(串列是 O(n)),適合大量查詢場景:

1
2
3
4
5
6
# 大量查詢時優先用 set
valid_users = {"alice", "bob", "charlie", "david"}

username = "alice"
if username in valid_users:
    print("使用者存在")

集合運算#

1
2
a = {1, 2, 3, 4, 5}
b = {3, 4, 5, 6, 7}

聯集(Union)#

1
2
3
# a 或 b 中的所有元素
print(a | b)           # {1, 2, 3, 4, 5, 6, 7}
print(a.union(b))      # 同上

交集(Intersection)#

1
2
3
# a 和 b 共同有的元素
print(a & b)                   # {3, 4, 5}
print(a.intersection(b))       # 同上

差集(Difference)#

1
2
3
4
5
6
# 在 a 但不在 b 的元素
print(a - b)                   # {1, 2}
print(a.difference(b))         # 同上

# 在 b 但不在 a 的元素
print(b - a)                   # {6, 7}

對稱差集(Symmetric Difference)#

1
2
3
# 只在 a 或只在 b 的元素(排除共同元素)
print(a ^ b)                          # {1, 2, 6, 7}
print(a.symmetric_difference(b))      # 同上

子集合與超集合#

1
2
3
4
5
6
7
8
9
a = {1, 2, 3}
b = {1, 2, 3, 4, 5}

print(a.issubset(b))     # True(a 是 b 的子集合)
print(b.issuperset(a))   # True(b 是 a 的超集合)

# 兩個集合沒有共同元素
print(a.isdisjoint({6, 7}))  # True
print(a.isdisjoint({3, 6}))  # False

集合推導式#

集合推導式(Set Comprehension)語法與串列推導式幾乎相同,差別只在外側用大括號 {} 而非方括號,結果自動去重且無序。

{運算式 for 變數 in 可迭代物件}
{運算式 for 變數 in 可迭代物件 if 條件}

基本形式與自動去重#

1
2
3
4
5
6
7
8
9
numbers = [1, 2, 2, 3, 3, 4, 5]

# 串列推導式 → 保留重複,有序
list_result = [x ** 2 for x in numbers]
print(list_result)   # [1, 4, 4, 9, 9, 16, 25]

# 集合推導式 → 自動去重,無序
set_result = {x ** 2 for x in numbers}
print(set_result)    # {1, 4, 9, 16, 25}

加入條件#

1
2
3
4
5
6
7
8
# 只取偶數的平方
even_squares = {x ** 2 for x in range(1, 11) if x % 2 == 0}
print(even_squares)  # {4, 16, 36, 64, 100}

# 從字串清單中取出首字母(去重)
words = ["apple", "avocado", "banana", "blueberry", "cherry"]
initials = {w[0] for w in words}
print(initials)   # {'a', 'b', 'c'}(順序不固定)

與串列推導式的比較#

串列推導式 [...]集合推導式 {...}
結果型別listset
保留重複❌(自動去重)
保留順序❌(無序)
適合用途需要順序或重複時只關心「哪些值存在」時

實戰範例#

去除串列重複元素#

1
2
3
data = [1, 3, 2, 3, 1, 4, 2, 5]
unique = sorted(set(data))
print(unique)  # [1, 2, 3, 4, 5]

找出兩個串列的共同元素#

1
2
3
4
5
list1 = ["Alice", "Bob", "Charlie", "David"]
list2 = ["Bob", "David", "Eve", "Frank"]

common = set(list1) & set(list2)
print(common)  # {'Bob', 'David'}

找出只在其中一個串列的元素#

1
2
3
4
only_in_1 = set(list1) - set(list2)
only_in_2 = set(list2) - set(list1)
print(only_in_1)  # {'Alice', 'Charlie'}
print(only_in_2)  # {'Eve', 'Frank'}

統計文章中不重複的單字數#

1
2
3
4
5
6
7
text = "to be or not to be that is the question"
words = text.split()

unique_words = set(words)
print(f"總單字數:{len(words)}")          # 10
print(f"不重複單字數:{len(unique_words)}")  # 8
print(unique_words)

權限管理#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
admin_permissions = {"read", "write", "delete", "manage_users"}
editor_permissions = {"read", "write"}

user_role = "editor"
user_permissions = editor_permissions if user_role == "editor" else admin_permissions

# 檢查是否有某權限
if "delete" in user_permissions:
    print("可以刪除")
else:
    print("無刪除權限")  # 無刪除權限

# 找出缺少的權限
missing = admin_permissions - user_permissions
print(f"缺少的權限:{missing}")  # {'delete', 'manage_users'}