在Python中检查元素是否属于集合

13

你好,我已经编码了几个月并掌握了基础知识,但是我遇到了一个固定会员问题,找不到解决方法。

我有一系列整数对的列表,我想删除其中包含“a”整数的列表。我认为使用集合是最简单的方法。下面是代码:

## This is the item to test against. 
a = set([3]) 
## This is the list to test.      
groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]     

## This is a list that will contain the lists present
## in groups which do not contain "a"
groups_no_a = []        

for group in groups:
    group = set(group)
    if a in group:
        groups_no_a.append(group)
    ## I thought the problem had something to do with
    ## clearing the variable so I put this in,   
    ## but to no remedy. 
    group.clear()  


print groups_no_a 

我之前尝试使用 s.issubset(t),直到意识到这个方法测试的是 s 中的每一个元素是否在 t 中。

谢谢!

4个回答

8

您想测试是否没有交集

if not a & group:

或者

if not a.intersection(group):

或者反过来,这些集合互斥
if a.isdisjoint(group):

该方法的表单可以接受任何可迭代对象,甚至无需将“group”转换为集合。以下一行代码也可以实现相同的功能:
groups_no_a = [group for group in groups if a.isdisjoint(group)]

演示:

>>> a = set([3]) 
>>> groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]     
>>> [group for group in groups if a.isdisjoint(group)]
[[1, 2], [5, 4]]

如果您只测试一个元素,那么创建集合的成本可能比测试成员获得的性能收益更高,所以只需执行:

3 not in group

其中group是一个短列表。

您可以使用timeit模块来比较Python代码的不同部分,以查看哪种代码最适合您特定的典型列表大小。


@user2387370:而且对于这个任务,集合更快;one_element in somelist必须扫描列表。 - Martijn Pieters
我甚至没有意识到“disjoint”选项,因为它在链接中有点隐藏。 - grasshopper
@user2387370:也许原帖只是将情况简化为非常小的子集。如果没有原帖的反馈,我们就不知道。 - Martijn Pieters
@MartijnPieters 评论的存在表明这是实际的代码。无论如何,如果问题只是“如何检查列表中是否存在元素?”,你会提到集合吗? - rlms
对于那些好奇的人,我想做的是:我有一个如下所示的列表:[[错误,[[group_item_1,group_item_2],[... ],[...],[...]]],[更多类似于此前面的],[...]],我想获取具有最小错误且在group_item_1或group_item_2中没有“a”的项。这些列表已经按错误排序。我差不多做到了:D - grasshopper
显示剩余6条评论

4
也许你可以使用列表推导式(List Comprehension)来实现:链接
a = 3
groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]
print [x for x in groups if a not in x]

根据评论进行编辑:

好吧,对于那些好奇的人,我想做的是:我有一个列表,如下所示:[[error,[[group_item_1,group_item_2],[...],[...],[...]]],[更多类似上一个],[...]],我想获取误差最小且不包含"a"在group_item_1或group_item_2中的项目。这些列表已经按错误排序。我差不多弄明白了:D

这应该能满足要求:

from itertools import chain, iterfilter

def flatten(listOfLists):
    "Flatten one level of nesting"
    return chain.from_iterable(listOfLists)


errors_list =  [ ['error0', [ [30, 2], [3, 4], [1, 2], [5, 4], [4, 3] ] ], ['error1', [ [31, 2], [3, 4], [1, 2], [5, 4], [4, 3] ] ] ]

a = 30
result = next(ifilter(lambda err: a not in flatten(err[1]), reversed(errors_list)), None)

print result #finds error1 as it has no 30 on its list

0
不妨尝试以下方法,而不是使用 a = set([3]):
a = 3
groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]
groups_no_a = [group for group in groups if a not in group]

-1

这里不需要使用集合,可以在列表中测试元素的成员身份。您似乎也有in,我认为您应该使用not in

这段代码与您的类似,应该可以工作:

## This is the item to test against. 
a = 3
## This is the list to test.      
groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]     

## This is a list that will contain the lists present
## in groups which do not contain a
groups_no_a = []        

for group in groups:
    if a not in group:
        groups_no_a.append(group)

print groups_no_a

然而,一种更短、更符合Python风格的方法是使用列表推导式

groups_no_a = [i for i in groups if a not in i]

如果你正在测试一个项目是否在一个非常长的列表中,为了提高性能,应该使用集合(sets)而不是列表。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接