Python如何实现返回两个列表非公共元素的函数?
修正并优化你的
nocommons函数 咱们先看看你原代码里的几个问题:
- 遍历列表时直接修改原列表(
l1.pop),会导致遍历过程跳过元素——列表长度变化后,后续元素前移,原本该遍历的元素会被漏掉。 - 直接修改传入的列表参数,会意外改变外部的原列表,这一般不是我们想要的行为。
- Python3里
print是函数,必须加括号调用,原代码的print nocommons(...)会触发语法错误。
先给你修正后的可用版本
这个版本会先复制输入列表,避免修改原数据,同时保证遍历过程正常:
def nocommons(l1, l2): # 复制原列表,避免修改外部传入的列表 list1 = l1.copy() list2 = l2.copy() # 遍历原l1的元素,操作复制后的列表 for num in l1: if num in list2: list1.remove(num) list2.remove(num) return list1 + list2 # 测试调用,注意print加括号 print(nocommons([1,4,6],[1,4,5])) # 输出 [6,5]
更优的实现方式
根据你的需求,分两种场景给你推荐更高效的写法:
场景1:不关心元素重复次数,只需要去重后的非公共元素
用集合的对称差集可以一行搞定,效率极高(时间复杂度O(n+m)):
def nocommons(l1, l2): # 对称差集就是两个集合中所有不属于交集的元素 return list(set(l1).symmetric_difference(set(l2))) print(nocommons([1,4,6],[1,4,5])) # 输出 [5,6](集合是无序的,顺序可能和预期不同)
⚠️ 注意:集合会自动去重,而且结果是无序的,如果需要保留原列表的元素顺序,可以调整写法:
def nocommons(l1, l2): set1, set2 = set(l1), set(l2) # 先保留l1中不在l2的元素,再保留l2中不在l1的元素 return [num for num in l1 if num not in set2] + [num for num in l2 if num not in set1] print(nocommons([1,4,6],[1,4,5])) # 输出 [6,5],和原预期顺序一致
场景2:需要保留元素的重复次数(比如l1=[1,1,2], l2=[1,3],期望返回[1,2,3])
可以用collections.Counter来统计元素出现次数,然后计算两个列表独有的元素:
from collections import Counter def nocommons(l1, l2): count1 = Counter(l1) count2 = Counter(l2) # 计算每个列表中比另一个列表多出来的元素 unique_l1 = count1 - count2 unique_l2 = count2 - count1 # 展开成最终列表 return list(unique_l1.elements()) + list(unique_l2.elements()) # 测试案例 print(nocommons([1,4,6],[1,4,5])) # 输出 [6,5] print(nocommons([1,1,2], [1,3])) # 输出 [1,2,3]
这种写法既保留了元素的重复次数,又能准确计算非公共元素,代码也很简洁。
内容的提问来源于stack exchange,提问作者Kostas Petrakis
相关产品推荐
相关产品推荐

