python - Python:如何获取仅出现在一组列表中的项目?
问题描述
我想创建一个函数,该函数采用一个或多个集合的列表并找到列表中所有集合的对称差异,即结果应该是一组值,每个值只包含在一个个体中套。(如果我错认为这是对称差异,请纠正我。)
例如:
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 3, 7])
>>> s4 = set([2, 5, 9])
>>> myfunc([s1, s2, s3, s4])
{1, 4, 5, 7, 9}
有什么内置的东西可以用来代替上面的myfunc
吗?还是我使用这样的东西:
def myfunc(sets: List[set]) -> set:
sd = set()
goners = set()
for s in sets:
still_ok = s - goners
sd = sd.symmetric_difference(still_ok)
goners = goners.union(s.difference(sd))
return sd
有没有更好/更有效/“Pythonic”的方法来做到这一点?
解决方案
那这个呢:
from collections import Counter
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
s3 = set([2, 3, 7])
s4 = set([2, 5, 9])
print([k for k,v in Counter((*s1,*s2,*s3,*s4)).items() if v == 1])
Eventho 这看起来不错,因为它是一个单线器,你必须记住它比你自己的方法慢一点:
In [85]: def nicefunc(sets):
...: return [k for k,v in Counter(itertools.chain.from_iterable(sets)).items() if v == 1]
...:
In [86]: def nicefunc2(sets):
...: return [k for k,v in Counter( [i for s in sets for i in s]).items() if v == 1]
...:
In [87]: def nicefunc3():
...: return [k for k,v in Counter((*s1,*s2,*s3,*s4)).items() if v == 1]
...:
In [88]: def myfunc(sets):
...: sd = set()
...: goners = set()
...: for s in sets:
...: still_ok = s - goners
...: sd = sd.symmetric_difference(still_ok)
...: goners = goners.union(s.difference(sd))
...: return sd
...:
In [89]: sets = [s1, s2, s3, s4]
In [90]: %timeit myfunc(sets)
2.25 µs ± 2.53 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [91]: %timeit nicefunc(sets)
3.64 µs ± 23 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [92]: %timeit nicefunc2(sets)
3.79 µs ± 11.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [94]: %timeit nicefunc3()
3.64 µs ± 18.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
您还可以选择另一种方法,它仍然是单行但速度更快:
In [152]: def coolfunc(sets):
...: return set.union(*[sets[i]-set.union(*sets[:i],*sets[i+1:]) for i in range(len(sets))])
In [153]: coolfunc(sets)
Out[153]: {1, 4, 5, 7, 9}
In [154]: %timeit coolfunc(sets)
3.34 µs ± 19.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
但是,正如@VBrail 所指出的,您对集合集合的对称集合差异的定义是错误的。这是一个用于计算集合的实际对称集差异的单行方法,定义为
集合的对称差异仅包含集合维基百科中奇数个集合中的元素
from functools import reduce
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
s3 = set([2, 3, 7])
s4 = set([2, 5, 9])
sets = [s1,s2,s3,s4]
reduce(set.symmetric_difference, sets)
{1、3、4、5、7、9}
推荐阅读
- c++ - 骑士巡回赛问题没有给出正确的输出
- php - 如果数字大于 12,则使用 PHP 使数字从 1 开始
- python - 复制行和更改值 MySQL
- angular - Angular 9 - 如果输入由浏览器自动填充,则表单在 onInit 无效
- shell - csvcut:错误:无法识别的参数:filename.csv
- ruby-on-rails - Rails 使用 httparty 将 JSON 解析为外部 URL
- 2sxc - 从自定义 FormController 调用异步模块
- coq - 如何解决 Coq 中的矛盾
- javascript - 将 NodeJS 包作为 SubModule 从子目录到子目录的 Github 页面
- javascript - 页码中的功能空间如何?