减去集合列表

Ste*_*eve 11 python algorithm list-comprehension list set

给出一组集合:

allsets = [set([1, 2, 4]), set([4, 5, 6]), set([4, 5, 7])]
Run Code Online (Sandbox Code Playgroud)

什么是pythonic方法来计算与其他集不重叠的元素集的相应列表?

only = [set([1, 2]), set([6]), set([7])]
Run Code Online (Sandbox Code Playgroud)

有没有办法用列表理解来做到这一点?

use*_*ica 19

要避免二次运行时,您需要进行初始传递以确定哪些元素出现在多个集合中:

import itertools
import collections
element_counts = collections.Counter(itertools.chain.from_iterable(allsets))
Run Code Online (Sandbox Code Playgroud)

然后,您只需创建一个集合列表,保留仅出现一次的所有元素:

nondupes = [{elem for elem in original if element_counts[elem] == 1}
            for original in allsets]
Run Code Online (Sandbox Code Playgroud)

或者,代替构建nondupeselement_counts直接,我们可以使一个附加通构建一套出现在正好一个输入所有元件.这需要一个额外的声明,但它允许我们利用&运算符进行集合交集,以使列表理解更短,更有效:

element_counts = collections.Counter(itertools.chain.from_iterable(allsets))
all_uniques = {elem for elem, count in element_counts.items() if count == 1}
#                                                     ^ viewitems() in Python 2.7
nondupes = [original & all_uniques for original in allsets]
Run Code Online (Sandbox Code Playgroud)

时间似乎表明使用all_uniques集合可以为整个重复消除过程产生大量加速.对于大量重复的输入集,它在Python 3上的速度提高了大约3.5倍,尽管在Python 2上整个重复消除过程只有大约30%的加速,因为更多的运行时由构造计数器来控制.这种加速是相当可观的,但并不像通过element_counts首先使用来避免二次运行时那么重要.如果您使用的是Python 2并且此代码对速度至关重要,那么您需要使用普通代码dictcollections.defaultdict代替a代码Counter.

另一种方法是dupes从munk中建议element_counts使用original - dupes而不是original & all_uniques在列表理解中构造一个集合.这是否执行比使用更好或更差集和将取决于重复你输入的程度,什么Python版本你,但它并不显得做出多大的差别两种方式.all_uniques&

  • 当然是更好的方式.OP的一些链接1. [`chain.from_iterable`](https://docs.python.org/3/library/itertools.html#itertools.chain.from_iterable)2.[`collections.Counter`](https ://docs.python.org/3/library/collections.html#collections.Counter) (2认同)
  • 字面语法可以更好[[elem for elem in original ...}] (2认同)

Bha*_*Rao 8

是的,它可以完成,但几乎不是pythonic

>>> [(i-set.union(*[j for j in allsets if j!= i])) for i in allsets]   
[set([1, 2]), set([6]), set([7])]
Run Code Online (Sandbox Code Playgroud)

可以在文档中找到有关集合的一些参考.该*操作被称为拆箱操作.

  • eww同意了.像瘟疫一样避免这种情况.喜欢一些冗长的循环(但是很棒的工作Bhargav!) (2认同)

mun*_*unk 6

使用计数器和理解的稍微不同的解决方案,利用-操作员设置差异.

from itertools import chain
from collections import Counter

allsets = [{1, 2, 4}, {4, 5, 6}, {4, 5, 7}]
element_counts = Counter(chain.from_iterable(allsets))

dupes = {key for key in element_counts 
         if element_counts[key] > 1}

only = [s - dupes for s in allsets]
Run Code Online (Sandbox Code Playgroud)