跳到主要内容

Python 集合

什么是集合

集合(Set)是Python中一种无序且不重复的可变数据结构,用于存储唯一的元素。集合是基于数学中的集合理论实现的,支持并集、交集、差集等操作。在Python中,集合的标识是使用大括号 {} 包围的元素,或使用 set() 函数创建。

备注

虽然集合使用大括号表示,但空集合不能用 {} 表示,因为这表示的是空字典。创建空集合必须使用 set()

集合的主要特点:

  • 唯一性:集合中的元素不会重复
  • 无序性:元素没有特定的顺序
  • 可变性:可以添加或删除元素
  • 不可索引:不能通过索引访问元素
  • 元素必须是可哈希的:只能包含不可变的数据类型(如字符串、数字、元组)

创建集合

使用大括号创建集合

python
# 创建一个包含多个元素的集合
fruits = {"apple", "banana", "cherry"}
print(fruits) # 输出: {"cherry", "banana", "apple"} (顺序可能不同)

# 创建含有重复元素的集合(重复元素会被自动去除)
numbers = {1, 2, 2, 3, 4, 4, 5}
print(numbers) # 输出: {1, 2, 3, 4, 5}

使用set()函数创建集合

python
# 从列表创建集合
colors_list = ["red", "blue", "green", "blue", "red"]
colors_set = set(colors_list)
print(colors_set) # 输出: {"red", "blue", "green"}

# 创建空集合
empty_set = set()
print(empty_set) # 输出: set()
print(type(empty_set)) # 输出: <class 'set'>

# 注意:这不是空集合,而是空字典
not_set = {}
print(type(not_set)) # 输出: <class 'dict'>

集合的基本操作

添加元素

python
fruits = {"apple", "banana", "cherry"}

# 添加单个元素
fruits.add("orange")
print(fruits) # 输出可能是: {"orange", "cherry", "banana", "apple"}

# 添加多个元素
fruits.update(["mango", "grapes"])
print(fruits) # 输出可能是: {"mango", "orange", "cherry", "banana", "apple", "grapes"}

删除元素

python
fruits = {"apple", "banana", "cherry", "orange", "kiwi"}

# 使用remove()方法(如果元素不存在,会引发KeyError)
fruits.remove("banana")
print(fruits) # 输出可能是: {"cherry", "apple", "orange", "kiwi"}

# 使用discard()方法(如果元素不存在,不会引发错误)
fruits.discard("kiwi")
fruits.discard("pineapple") # 不存在,但不会报错
print(fruits) # 输出可能是: {"cherry", "apple", "orange"}

# 使用pop()方法随机移除一个元素并返回它
popped_item = fruits.pop()
print(popped_item) # 输出可能是集合中的任意一个元素
print(fruits) # 输出的集合会少一个元素

# 清空集合
fruits.clear()
print(fruits) # 输出: set()

集合的长度

python
numbers = {1, 2, 3, 4, 5}
print(len(numbers)) # 输出: 5

检查元素是否存在

python
fruits = {"apple", "banana", "cherry"}

print("banana" in fruits) # 输出: True
print("pineapple" in fruits) # 输出: False

集合的数学操作

集合支持多种数学操作,这是Python集合最强大的特性之一。

并集(Union)

并集包含两个集合中的所有元素(不重复)。

python
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# 使用union()方法
union_set = set1.union(set2)
print(union_set) # 输出: {1, 2, 3, 4, 5, 6, 7, 8}

# 使用|操作符
union_set = set1 | set2
print(union_set) # 输出: {1, 2, 3, 4, 5, 6, 7, 8}

交集(Intersection)

交集包含两个集合中共有的元素。

python
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# 使用intersection()方法
intersection_set = set1.intersection(set2)
print(intersection_set) # 输出: {4, 5}

# 使用&操作符
intersection_set = set1 & set2
print(intersection_set) # 输出: {4, 5}

差集(Difference)

差集包含在第一个集合中但不在第二个集合中的元素。

python
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# 使用difference()方法
difference_set = set1.difference(set2)
print(difference_set) # 输出: {1, 2, 3}

# 使用-操作符
difference_set = set1 - set2
print(difference_set) # 输出: {1, 2, 3}

对称差集(Symmetric Difference)

对称差集包含在两个集合中,但不同时存在于两个集合中的元素。

python
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# 使用symmetric_difference()方法
symm_diff = set1.symmetric_difference(set2)
print(symm_diff) # 输出: {1, 2, 3, 6, 7, 8}

# 使用^操作符
symm_diff = set1 ^ set2
print(symm_diff) # 输出: {1, 2, 3, 6, 7, 8}

子集和超集检查

python
set1 = {1, 2, 3}
set2 = {1, 2, 3, 4, 5}

# 检查set1是否为set2的子集
print(set1.issubset(set2)) # 输出: True
print(set1 <= set2) # 输出: True

# 检查set2是否为set1的超集
print(set2.issuperset(set1)) # 输出: True
print(set2 >= set1) # 输出: True

不可变集合 - frozenset

Python还提供了不可变版本的集合,称为frozenset。一旦创建,它的元素就不能被修改。

python
# 创建一个frozenset
frozen = frozenset([1, 2, 3, 4, 5])
print(frozen) # 输出: frozenset({1, 2, 3, 4, 5})

# 尝试修改frozenset会引发错误
# frozen.add(6) # 这行会引发AttributeError错误

不可变集合的主要用途是作为字典的键或其他集合的元素。

集合推导式

类似于列表推导式,Python也支持集合推导式,用于根据现有可迭代对象创建新集合。

python
# 创建一个包含1到10的平方的集合
squares = {x**2 for x in range(1, 11)}
print(squares) # 输出: {64, 1, 4, 36, 100, 9, 16, 49, 81, 25} (顺序不定)

# 从字符串创建集合,只包含元音字母
text = "hello world"
vowels = {char for char in text if char in 'aeiou'}
print(vowels) # 输出: {'e', 'o'}

实际应用场景

1. 去重处理

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

python
# 去除列表中的重复元素
numbers = [1, 2, 2, 3, 4, 4, 5, 6, 6]
unique_numbers = list(set(numbers))
print(unique_numbers) # 输出: [1, 2, 3, 4, 5, 6] (顺序可能不同)

# 去除字符串中的重复字符
text = "hello"
unique_chars = ''.join(set(text))
print(unique_chars) # 输出可能是: "ehlo" (顺序不定)

2. 数据比较和分析

python
# 比较两个数据集的差异
users_day1 = {"Alice", "Bob", "Charlie", "David"}
users_day2 = {"Bob", "Charlie", "Eve", "Frank"}

# 哪些用户在第一天在线但第二天不在线?
left_users = users_day1 - users_day2
print(left_users) # 输出: {"Alice", "David"}

# 哪些是新用户?
new_users = users_day2 - users_day1
print(new_users) # 输出: {"Eve", "Frank"}

# 哪些用户在这两天都在线?
active_users = users_day1 & users_day2
print(active_users) # 输出: {"Bob", "Charlie"}

3. 成员资格测试

比起列表和元组,集合的成员资格测试(检查一个元素是否存在)效率更高:

python
# 假设我们有一个大型列表和一个大型集合
import time

# 创建一个包含百万个元素的列表和集合
large_list = list(range(1000000))
large_set = set(large_list)

# 测试在列表中查找元素的时间
start = time.time()
999999 in large_list
end = time.time()
print(f"在列表中查找耗时: {end - start} 秒") # 可能需要相当长的时间

# 测试在集合中查找元素的时间
start = time.time()
999999 in large_set
end = time.time()
print(f"在集合中查找耗时: {end - start} 秒") # 通常会快得多
提示

对于需要频繁进行成员资格测试的大型数据集,优先选择使用集合而不是列表。

4. 过滤唯一元素

python
# 过滤出仅出现一次的元素
items = ["apple", "banana", "apple", "orange", "banana", "grape"]

# 计算每个元素的出现次数
count_dict = {}
for item in items:
if item in count_dict:
count_dict[item] += 1
else:
count_dict[item] = 1

# 过滤出仅出现一次的元素
unique_items = {item for item, count in count_dict.items() if count == 1}
print(unique_items) # 输出: {"orange", "grape"}

总结

Python集合是一种非常有用的数据结构,特别适合处理唯一元素集和执行集合操作。它们的主要优势在于:

  1. 快速的成员资格测试:O(1) 复杂度的查找操作
  2. 元素唯一性:自动去除重复项
  3. 数学集合操作:支持并集、交集、差集等操作
  4. 简洁的语法:提供直观的操作符和方法

然而,集合也有一些限制:

  • 无序性:元素没有固定顺序
  • 只能包含可哈希对象:不能包含列表、字典或其他集合作为元素
  • 无法通过索引访问:不支持索引或切片操作

理解何时使用集合,何时使用列表、元组或字典,是掌握Python数据结构的关键部分。

练习

  1. 创建一个包含1-10所有偶数的集合。
  2. 给定两个字符串,找出在第一个字符串中出现但在第二个字符串中不出现的所有字符。
  3. 编写一个函数,接受一个列表作为参数,返回列表中所有重复的元素。
  4. 使用集合推导式创建一个集合,包含1-100中所有能被3或5整除的数字。
  5. 实现一个简单的朋友推荐系统:给定用户A的朋友集合和每个朋友的朋友集合,找出可能推荐给用户A的人(是A的朋友的朋友,但不是A自己的朋友)。

额外资源