Skip to content

10|集合

集合是无序、不重复的元素集合。它的核心价值是去重和集合运算。判断成员是否存在、求交集并集差集、过滤重复项——这些操作在集合上的效率远高于列表。

一、创建集合

python
# 字面量(注意:空 {} 是字典,不是集合)
tags = {"python", "go", "shell"}

# 空集合
empty = set()

# 从列表/元组/字符串创建
set([1, 2, 2, 3])     # {1, 2, 3},自动去重
set("hello")          # {'h', 'e', 'l', 'o'}

集合里的元素必须是不可变类型(可哈希),和字典的键要求一致。列表、字典不能作为集合的元素。

二、增删改查

python
s = {1, 2, 3}

# 添加
s.add(4)           # {1, 2, 3, 4}
s.update([5, 6])   # {1, 2, 3, 4, 5, 6},批量添加

# 删除
s.remove(3)        # 删除 3,不存在抛 KeyError
s.discard(10)      # 删除 10,不存在不报错
s.pop()            # 随机删除并返回一个元素
s.clear()          # 清空

remove()discard() 的区别:不确定元素是否存在时,用 discard() 更安全。

三、集合运算

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

a | b     # {1, 2, 3, 4, 5, 6},并集
a & b     # {3, 4},交集
a - b     # {1, 2},差集(在 a 中但不在 b 中)
b - a     # {5, 6},差集(在 b 中但不在 a 中)
a ^ b     # {1, 2, 5, 6},对称差集(只在其中一个集合中)

也可以用方法:

python
a.union(b)          # 并集
a.intersection(b)   # 交集
a.difference(b)     # 差集
a.symmetric_difference(b)   # 对称差集

方法支持传入任意可迭代对象,而运算符要求两边都是集合:

python
a.union([5, 6])        # 可以,列表也能传
a | [5, 6]             # TypeError

四、判断关系

python
a = {1, 2}
b = {1, 2, 3, 4}

a < b        # True,a 是 b 的真子集
a <= b       # True,a 是 b 的子集
b > a        # True,b 是 a 的真超集
a.isdisjoint({5, 6})   # True,没有共同元素

五、去重

去重是集合最常见的用途:

python
items = ["a", "b", "a", "c", "b", "a"]
unique = list(set(items))
# {'a', 'b', 'c'} → 转成列表,但顺序不保证

如果需要保留原顺序的去重(Python 3.7+):

python
unique = list(dict.fromkeys(items))
# ['a', 'b', 'c'],利用字典保持插入顺序的特性

六、成员判断的效率

集合的成员判断(in)时间复杂度是 O(1),列表是 O(n)。数据量大时,这个差距很明显:

python
large_list = list(range(100_000))
large_set = set(large_list)

99_999 in large_list   # 慢,需要遍历
99_999 in large_set    # 快,直接定位

需要频繁判断"某个值是否在集合中"时,先把数据转成集合。

七、frozenset

集合是可变的,不能作为字典的键或另一个集合的元素。frozenset 是不可变的集合,解决了这个问题:

python
fs = frozenset([1, 2, 3])
fs.add(4)    # AttributeError: 'frozenset' object has no attribute 'add'

cache = {}
cache[fs] = "value"   # 可以,frozenset 可哈希

frozenset 支持所有集合运算(|, &, -, ^),但不支持增删改。

记忆锚点:集合无序不重复,元素必须不可变;add() 加单个,update() 批量;discard() 安全删除;| & - ^ 是并交差对称差;集合的 in 判断是 O(1),列表是 O(n);frozenset 是不可变集合,可作字典键。