Python 从集合中移除另一个集合
根据我对Python 2.7.2文档中关于内置类型5.7集合类型的理解,应该可以通过将集合A传递给set.remove(elem)
或set.discard(elem)
来从集合B中移除集合A的元素。
在2.7.2的文档中提到:
注意,
__contains__()
、remove()
和discard()
方法的elem参数可以是一个集合。
我理解这意味着我可以将一个set
传递给remove(elem)
或discard(elem)
,这样所有这些元素就会从目标集合中移除。我会用这个做一些奇怪的事情,比如从字符串中移除所有元音字母,或者从词频直方图中移除所有公共单词。以下是测试代码:
Python 2.7.2 (default, Jun 12 2011, 14:24:46) [M...
Type "help", "copyright", "credits" or "license"
>>> a = set(range(10))
>>> b = set(range(5,10))
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
set([8, 9, 5, 6, 7])
>>> a.remove(b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: set([8, 9, 5, 6, 7])
>>> a.discard(b)
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>
我期望返回:
>>> a
set([0, 1, 2, 3, 4])
我知道我可以用a.difference(b)
来实现,这会返回一个新的集合;或者用set.difference_update(other)
;或者用集合运算符a -= b
,这些都会直接修改集合。
那么这是不是文档中的一个错误?set.remove(elem)
真的不能接受一个集合作为参数吗?还是文档提到的是集合的集合?考虑到difference_update
达到了我的理解,我猜测是后者。
这样说清楚了吗?
编辑 经过3年的额外(一些是专业的)Python工作,最近又回到这个问题,我现在意识到我实际上想做的事情可以用:
>>> c = a.difference(b)
set([0,1,2,3,4])
这就是我最初想要得到的。
编辑
经过4年更多的Python开发……我意识到这个操作可以用集合字面量和-
运算符更简洁地表达;而且更完整地展示集合差异是非交换的。
>>> a={0,1,2,3}
>>> b={2,3,4,5}
>>> a-b
set([0, 1])
>>> b-a
set([4, 5])
5 个回答
在Python中,你不能有“集合的集合”,因为集合是可变的,也就是说它的内容可以改变。相反,你可以有“不可变集合的集合”,也就是使用frozenset
。另一方面,你可以对集合使用__contains__()
、remove()
和discard()
这些方法。下面是一个例子:
a = set([frozenset([2])])
set([2]) in a # you get True
a.remove(set([2])) # a is now empty
所以,回答你的问题,文档中提到的是“不可变集合的集合”。
set1-set2
set1 = {0,1,2,3}
set2 = {2,3,4,5}
set1 - set2 # {0, 1}
set2 - set1 # {4, 5}
不过要注意的是,不管出于什么原因,你不能用“+”号来合并集合(sets)在Python里...
你已经回答了这个问题。它指的是一组集合(实际上是包含不可变集合的集合)。
你提到的段落开头是:
注意,__contains__()、remove()和discard()方法中的elem参数可以是一个集合。
这意味着在a.remove(b)
中,b
可以是一个集合,然后接着说:
为了支持查找等效的不可变集合,在搜索过程中,elem集合会暂时被改变,然后再恢复。在搜索期间,elem集合不应该被读取或改变,因为它没有实际的意义。
这就是说,如果b
是一个集合,a.remove(b)
会在a
中查找与b
等效的不可变集合并将其移除(如果不存在则会抛出KeyError
错误)。