Python 使用集合找出两个列表的交集(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言
在编程中,我们常常需要比较两个列表中的元素,找出它们共同拥有的项。例如,电商系统中可能需要比较两个用户的购物车,数据分析时需要筛选出两个数据集的共同样本。虽然可以通过循环遍历逐一比较元素,但这样的方法效率较低,尤其在处理大数据时。
Python 提供了集合(Set)这一数据结构,它天然支持快速的交集运算。本文将从基础概念讲起,结合实际案例,深入探讨如何使用集合高效找出两个列表的交集。无论你是编程初学者还是希望优化代码的中级开发者,都能从中获得实用技巧。
列表与集合:数据结构的本质区别
列表(List)的特点
列表是 Python 中最常用的序列类型之一,具有以下特性:
- 有序性:元素按照插入顺序排列,可以通过索引访问。
- 可重复性:允许包含重复元素。
- 可变性:支持增删改操作。
例如:
shopping_list = ["苹果", "香蕉", "苹果", "橙子"]
print(shopping_list[0]) # 输出 "苹果"
集合(Set)的特点
集合是一种无序且唯一的数据结构,其核心特性包括:
- 无序性:元素不保存插入顺序。
- 唯一性:自动去重,元素不可重复。
- 高效性:底层基于哈希表实现,查找、添加和删除操作的时间复杂度均为 O(1)。
例如:
unique_fruits = {"苹果", "香蕉", "橙子"}
print("香蕉" in unique_fruits) # 输出 True
为什么集合适合求交集?
集合的唯一性和高效性使其成为求交集的天然选择:
- 去重特性:自动过滤重复元素,避免冗余计算。
- 快速查找:通过哈希表实现,查找元素的时间复杂度为 O(1),远快于列表的 O(n)。
交集操作:从基础到进阶
方法 1:使用 intersection()
方法
集合对象提供 intersection()
方法,直接返回两个集合的交集。
步骤说明:
- 将列表转换为集合。
- 调用
intersection()
方法,传入另一个集合。 - 将结果转换回列表(可选)。
示例代码:
list_a = [1, 2, 3, 4, 5]
list_b = [4, 5, 6, 7, 8]
set_a = set(list_a)
set_b = set(list_b)
common_elements = set_a.intersection(set_b)
print(common_elements) # 输出 {4, 5}
result_list = list(common_elements)
print(result_list) # 输出 [4, 5](顺序可能不同)
方法 2:使用 &
运算符
集合支持 &
运算符,其功能与 intersection()
完全相同,语法更简洁。
示例代码:
common_elements = set_a & set_b
print(common_elements) # 输出 {4, 5}
方法 3:直接操作列表(不推荐)
虽然可以通过双重循环遍历列表元素,但这种方法效率极低,尤其在处理大型数据时:
def find_common(list1, list2):
common = []
for item in list1:
if item in list2 and item not in common:
common.append(item)
return common
print(find_common(list_a, list_b)) # 输出 [4, 5]
性能对比:
| 方法 | 时间复杂度 | 适用场景 |
|---------------------|------------|--------------------------|
| 集合操作 | O(n) | 大数据、频繁操作 |
| 双重循环 | O(n²) | 小数据、无需优化 |
| 列表推导式 | O(n²) | 小数据、代码简洁性优先 |
进阶技巧:处理复杂场景
场景 1:嵌套列表的交集
如果列表元素是可变对象(如列表或字典),需要先将其转换为不可变类型(如元组或字符串)。
示例代码:
list_a = [[1, 2], [3, 4], [5, 6]]
list_b = [[3, 4], [7, 8], [5, 6]]
set_a = {tuple(item) for item in list_a}
set_b = {tuple(item) for item in list_b}
common_tuples = set_a & set_b
common_lists = [list(t) for t in common_tuples]
print(common_lists) # 输出 [[3, 4], [5, 6]]
场景 2:保留原始列表的顺序
集合会打乱元素顺序,若需保留原始列表的顺序,可结合列表推导式:
def ordered_intersection(list1, list2):
set2 = set(list2)
return [item for item in list1 if item in set2]
print(ordered_intersection([3, 2, 1], [2, 4, 3])) # 输出 [3, 2]
场景 3:处理大数据优化
当列表元素超过百万级时,可以考虑以下优化策略:
- 使用生成器表达式减少内存占用。
- 结合
set
的快速查找特性,避免不必要的循环。
实战案例:电商系统的商品对比
案例背景
某电商平台需要比较两个店铺的商品列表,找出共同销售的商品。
原始数据:
store1_products = ["手机", "耳机", "平板", "耳机", "充电器"]
store2_products = ["平板", "耳机", "笔记本", "充电器"]
实现步骤
- 去除重复项,转换为集合。
- 计算交集。
- 输出结果。
代码实现:
def find_common_products(store1, store2):
set1 = set(store1)
set2 = set(store2)
common = set1 & set2
return list(common)
common_products = find_common_products(store1_products, store2_products)
print("共同商品:", common_products) # 输出 ["耳机", "平板", "充电器"]
常见问题与解决方案
问题 1:元素不可哈希
如果列表元素是列表、字典等不可哈希的类型,转换为集合时会报错:
list_with_list = [[1, 2], [3, 4]]
set(list_with_list) # 报错:unhashable type: 'list'
解决方法:将元素转换为元组:
set([(1, 2), (3, 4)]) # 合法
问题 2:空列表的处理
若其中一个列表为空,交集结果也为空集合。需通过条件判断避免后续逻辑出错:
def safe_intersection(list1, list2):
set1 = set(list1) if list1 else set()
set2 = set(list2) if list2 else set()
return set1 & set2
print(safe_intersection([], ["a"])) # 输出空集合
问题 3:类型不一致
若两个列表的元素类型不同(如字符串和整数),交集会过滤所有元素。需统一类型后再处理:
list_a = ["1", "2", "3"]
list_b = [1, 2, 3]
common = set(list_a) & set(map(str, list_b))
print(common) # 输出 {"1", "2", "3"}
结论
通过集合操作,我们可以高效、简洁地找到两个列表的交集。本文从基础概念、代码实现到实际案例,逐步展示了这一方法的优势与细节。
- 核心知识点:
- 集合的无序性和唯一性使其成为交集运算的最佳工具。
intersection()
方法和&
运算符是求交集的两种主要方式。- 处理复杂数据类型时,需注意哈希性和类型统一。
希望本文能帮助你掌握这一实用技巧,并在实际开发中提升代码效率。如果遇到具体问题,欢迎在评论区讨论!