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集合是一种非常有用的数据结构,特别适合处理唯一元素集和执行集合操作。它们的主要优势在于:
- 快速的成员资格测试:O(1) 复杂度的查找操作
- 元素唯一性:自动去除重复项
- 数学集合操作:支持并集、交集、差集等操作
- 简洁的语法:提供直观的操作符和方法
然而,集合也有一些限制:
- 无序性:元素没有固定顺序
- 只能包含可哈希对象:不能包含列表、字典或其他集合作为元素
- 无法通过索引访问:不支持索引或切片操作
理解何时使用集合,何时使用列表、元组或字典,是掌握Python数据结构的关键部分。
练习
- 创建一个包含1-10所有偶数的集合。
- 给定两个字符串,找出在第一个字符串中出现但在第二个字符串中不出现的所有字符。
- 编写一个函数,接受一个列表作为参数,返回列表中所有重复的元素。
- 使用集合推导式创建一个集合,包含1-100中所有能被3或5整除的数字。
- 实现一个简单的朋友推荐系统:给定用户A的朋友集合和每个朋友的朋友集合,找出可能推荐给用户A的人(是A的朋友的朋友,但不是A自己的朋友)。