Python的集合(set)是一种无序、不重复元素的数据结构,常用于成员检测、去重和数学集合运算。与列表或元组不同,集合基于哈希表实现,查找操作的时间复杂度为O(1),因此在处理大量数据时性能优势明显。集合分为可变set和不可变frozenset两种类型,日常开发中最常用的是set。
创建集合非常简单:直接用大括号包裹元素,或使用set()函数从其他可迭代对象转换。注意空集合只能用set()创建,因为{}表示空字典。
- # 基本创建方式
- set1 = {1, 2, 3, 4, 5}
- set2 = set([1, 2, 3, 2, 1]) # 自动去重 -> {1, 2, 3}
- set3 = set("hello") # 字符拆解 -> {'h', 'e', 'l', 'o'}
复制代码
一、四种基本集合运算
1. 交集(& / intersection())
交集返回两个集合中都包含的元素。适用于找出共同好友、满足多重条件的记录等场景。
- set_a = {1, 2, 3, 4, 5}
- set_b = {4, 5, 6, 7, 8}
- # 运算符方式
- inter_op = set_a & set_b # {4, 5}
- # 方法方式(可传入多个集合)
- inter_method = set_a.intersection(set_b) # {4, 5}
复制代码
2. 并集(| / union())
并集返回两个集合中所有唯一元素,常用于合并多数据源、统计全部参与用户等。
- set_x = {1, 2, 3}
- set_y = {3, 4, 5}
- union_op = set_x | set_y # {1, 2, 3, 4, 5}
- union_method = set_x.union(set_y) # {1, 2, 3, 4, 5}
复制代码
3. 差集(- / difference())
差集返回只在第一个集合中出现、不在第二个集合中的元素。常用于找出新注册用户、未完成的任务、数据变更检测等。
- set_p = {1, 2, 3, 4, 5}
- set_q = {4, 5, 6}
- diff_op = set_p - set_q # {1, 2, 3}
- diff_method = set_p.difference(set_q) # {1, 2, 3}
复制代码
注意:差集运算结果依赖于操作数顺序,set_p - set_q与set_q - set_p结果不同。
4. 对称差集(^ / symmetric_difference())
对称差集返回两个集合中不重复的元素,即去掉交集部分后的所有元素。适用于统计只进行单一操作的用户、找出互斥数据等。
- set_m = {1, 2, 3, 4}
- set_n = {3, 4, 5, 6}
- sym_op = set_m ^ set_n # {1, 2, 5, 6}
- sym_method = set_m.symmetric_difference(set_n) # {1, 2, 5, 6}
复制代码
二、多重集合运算与比较
集合运算支持链式调用,可同时对多个集合进行运算。
- set1 = {1, 2, 3, 4}
- set2 = {3, 4, 5, 6}
- set3 = {4, 5, 6, 7}
- # 多重交集:三者共同的元素
- multi_inter = set1 & set2 & set3 # {4}
- # 多重并集:所有元素去重
- multi_union = set1 | set2 | set3 # {1,2,3,4,5,6,7}
- # 链式方法
- chain_inter = set1.intersection(set2).intersection(set3) # {4}
复制代码
集合比较运算可以判断子集、超集、相等、是否不相交:
- set_alpha = {1, 2, 3}
- set_beta = {1, 2, 3, 4, 5}
- set_gamma = {1, 2, 3}
- set_delta = {6, 7, 8}
- # 子集 / 真子集
- print(set_alpha <= set_beta) # True
- print(set_alpha < set_beta) # True
- # 超集 / 真超集
- print(set_beta >= set_alpha) # True
- print(set_beta > set_alpha) # True
- # 相等
- print(set_alpha == set_gamma) # True
- # 不相交(没有共同元素)
- print(set_alpha.isdisjoint(set_delta)) # True
复制代码
三、实战案例:数据分析与权限管理
案例1:电商用户行为分析
通过集合运算快速筛选不同行为组合的用户群体。
- all_users = {'user1','user2','user3','user4','user5'}
- purchased = {'user1','user3','user5'}
- browsed = {'user2','user3','user4'}
- # 购买但未浏览
- print(purchased - browsed) # {'user1','user5'}
- # 浏览但未购买
- print(browsed - purchased) # {'user2','user4'}
- # 既浏览又购买
- print(purchased & browsed) # {'user3'}
- # 有任一行为
- print(purchased | browsed) # {'user1','user2','user3','user4','user5'}
- # 只进行一种行为(对称差集)
- print(purchased ^ browsed) # {'user1','user2','user4','user5'}
复制代码
案例2:数据清洗与更新
当本地数据需要与远程数据同步时,通过差集和交集可以快速定位增删记录。
- current = {'A','B','C','D','E'}
- new_data = {'C','D','E','F','G'}
- # 需要删除的(当前有,新数据无)
- to_delete = current - new_data # {'A','B'}
- # 需要添加的(新数据有,当前无)
- to_add = new_data - current # {'F','G'}
- # 保持不变
- unchanged = current & new_data # {'C','D','E'}
复制代码
案例3:权限管理系统
用集合表示角色权限,升级或降级时只需简单的差集运算。
- admin = {'create','read','update','delete'}
- editor = {'create','read','update'}
- viewer = {'read'}
- # 查看者升级到编辑者需添加的权限
- print(editor - viewer) # {'create','update'}
- # 编辑者升级到管理员需添加的权限
- print(admin - editor) # {'delete'}
- # 所有角色共有的权限
- print(admin & editor & viewer) # {'read'}
复制代码
四、性能优化:成员检测与列表推导式
集合的哈希表结构使得成员检测非常快,适合海量数据下的包含判断。下面通过对比列表与集合的in操作时间,可以直观看到性能差距。
- import time
- large_list = list(range(1000000))
- large_set = set(range(1000000))
- t1 = time.time()
- print(999999 in large_list)
- list_time = time.time() - t1
- t1 = time.time()
- print(999999 in large_set)
- set_time = time.time() - t1
- print(f"列表耗时: {list_time:.6f}s, 集合耗时: {set_time:.6f}s, 提升倍率: {list_time/set_time:.1f}")
复制代码
在不需要去重且数据量不大的场景下,也可以使用列表推导式模拟交集运算,但要注意会包含重复元素,通常需要再转成set去重。
- list1 = [1, 2, 3, 4, 5]
- list2 = [4, 5, 6, 7, 8]
- # 列表推导式交集(结果可能有重复,视源数据而定)
- inter_list = [x for x in list1 if x in list2] # [4, 5]
- inter_set = set(inter_list) # {4, 5}
复制代码
五、总结
Python集合运算提供了简洁、高效的数据关系处理能力。正确使用交集、并集、差集、对称差集以及比较运算,可以减少循环判断,提升代码可读性和运行效率。在数据去重、关系分析、权限管理、性能敏感场景中,优先考虑集合而非列表,往往能带来数量级的性能提升。
掌握这些基础但强大的技巧,能让你的Python代码更加Pythonic。 |