如何检查下列项目是否在列表中?

我试图找到一个简短的方法来查看以下项目是否在列表中,但我的第一次尝试不起作用。除了编写一个函数来完成这个任务,还有一种简单的方法来检查列表中是否有多个项目中的一个。

>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True
525932 次浏览

想想代码到底说了什么!

>>> (1 or 2)
1
>>> (2 or 1)
2

这应该可以解释。Python显然实现了“lazy or”,这应该不足为奇。它是这样执行的:

def or(x, y):
if x: return x
if y: return y
return False

在第一个例子中,x == 1y == 2。在第二个例子中,反之亦然。这就是为什么它会根据它们的顺序返回不同的值。

>>> L1 = [2,3,4]
>>> L2 = [1,2]
>>> [i for i in L1 if i in L2]
[2]




>>> S1 = set(L1)
>>> S2 = set(L2)
>>> S1.intersection(S2)
set([2])

空列表和空集都是False,因此可以直接将其值用作真值。

我能想到的最好的办法是:

any([True for e in (1, 2) if e in a])

这将在一行中完成。

>>> a=[2,3,4]
>>> b=[1,2]
>>> bool(sum(map(lambda x: x in b, a)))
True

在某些情况下(例如唯一的列表元素),可以使用集合操作。

>>> a=[2,3,4]
>>> set(a) - set([2,3]) != set(a)
True
>>>

或者,使用set.isdisjoint ()

>>> not set(a).isdisjoint(set([2,3]))
True
>>> not set(a).isdisjoint(set([5,6]))
False
>>>

也许更懒一点:

a = [1,2,3,4]
b = [2,7]


print any((True for x in a if x in b))

我正在考虑托拜厄斯的解决方案的轻微变化:

>>> a = [1,2,3,4]
>>> b = [2,7]
>>> any(x in a for x in b)
True

当你考虑“检查a是否在b中”时,考虑哈希(在本例中是集合)。最快的方法是散列你想要检查的列表,然后检查其中的每一项。

这就是为什么Joe kobberg的回答是快速的:检查集合交集非常快。

当你没有大量的数据时,制作集合可能是浪费时间。所以,你可以做一组列表,检查每一项:

tocheck = [1,2] # items to check
a = [2,3,4] # the list


a = set(a) # convert to set (O(len(a)))
print [i for i in tocheck if i in a] # check items (O(len(tocheck)))

当您想要检查的项目数量很少时,差异可以忽略不计。但是在一个大的列表上检查大量的数字……

测试:

from timeit import timeit


methods = ['''tocheck = [1,2] # items to check
a = [2,3,4] # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',


'''L1 = [2,3,4]
L2 = [1,2]
[i for i in L1 if i in L2]''',


'''S1 = set([2,3,4])
S2 = set([1,2])
S1.intersection(S2)''',


'''a = [1,2]
b = [2,3,4]
any(x in a for x in b)''']


for method in methods:
print timeit(method, number=10000)


print


methods = ['''tocheck = range(200,300) # items to check
a = range(2, 10000) # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',


'''L1 = range(2, 10000)
L2 = range(200,300)
[i for i in L1 if i in L2]''',


'''S1 = set(range(2, 10000))
S2 = set(range(200,300))
S1.intersection(S2)''',


'''a = range(200,300)
b = range(2, 10000)
any(x in a for x in b)''']


for method in methods:
print timeit(method, number=1000)

速度:

M1: 0.0170331001282 # make one set
M2: 0.0164539813995 # list comprehension
M3: 0.0286040306091 # set intersection
M4: 0.0305438041687 # any


M1: 0.49850320816 # make one set
M2: 25.2735087872 # list comprehension
M3: 0.466138124466 # set intersection
M4: 0.668627977371 # any

始终快速的方法是做一个集合(列表),但交集在大数据集上工作最好!

a = {2,3,4}
if {1,2} & a:
pass

代码高尔夫版本。如果有意义,可以考虑使用set。 我发现这比一个列表理解更有可读性

一行,没有列表推导式。

>>> any(map(lambda each: each in [2,3,4], [1,2]))
True
>>> any(map(lambda each: each in [2,3,4], [1,5]))
False
>>> any(map(lambda each: each in [2,3,4], [2,4]))
True

简单。

_new_list = []
for item in a:
if item in b:
_new_list.append(item)
else:
pass

我收集了其他答案和评论中提到的几个解决方案,然后进行了速度测试。not set(a).isdisjoint(b)被证明是最快的,当结果是False时,它也没有减速太多。

这三次运行中的每一次都测试了ab可能配置的一个小样本。时间单位是微秒。

Any with generator and max
2.093 1.997 7.879
Any with generator
0.907 0.692 2.337
Any with list
1.294 1.452 2.137
True in list
1.219 1.348 2.148
Set with &
1.364 1.749 1.412
Set intersection explcit set(b)
1.424 1.787 1.517
Set intersection implicit set(b)
0.964 1.298 0.976
Set isdisjoint explicit set(b)
1.062 1.094 1.241
Set isdisjoint implicit set(b)
0.622 0.621 0.753

import timeit


def printtimes(t):
print '{:.3f}'.format(t/10.0),


setup1 = 'a = range(10); b = range(9,15)'
setup2 = 'a = range(10); b = range(10)'
setup3 = 'a = range(10); b = range(10,20)'


print 'Any with generator and max\n\t',
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup3).timeit(10000000))
print


print 'Any with generator\n\t',
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup3).timeit(10000000))
print


print 'Any with list\n\t',
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup3).timeit(10000000))
print


print 'True in list\n\t',
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup3).timeit(10000000))
print


print 'Set with &\n\t',
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup3).timeit(10000000))
print


print 'Set intersection explcit set(b)\n\t',
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup3).timeit(10000000))
print


print 'Set intersection implicit set(b)\n\t',
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup3).timeit(10000000))
print


print 'Set isdisjoint explicit set(b)\n\t',
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup3).timeit(10000000))
print


print 'Set isdisjoint implicit set(b)\n\t',
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup3).timeit(10000000))
print

在python3中,我们可以开始使用解包星号。给出两个列表:

bool(len({*a} & {*b}))

我不得不说,我的情况可能不是你想要的,但它可能会为你的想法提供另一种选择。

我已经尝试了set()和any()方法,但速度仍然有问题。所以我记得Raymond Hettinger说过,python里的所有东西都是字典,只要你可以就使用字典。这就是我所尝试的。

我使用一个带int的defaultdict表示负结果,并使用第一个列表中的项作为第二个列表的键(转换为defaultdict)。因为使用dict可以立即查找,所以可以立即知道该项是否存在于defaultdict中。我知道您并不总是要更改第二个列表的数据结构,但如果您能够从一开始就更改,那么就会快得多。您可能必须将list2(更大的列表)转换为defaultdict,其中key是您想从小列表中检查的潜在值,value是1(命中)或0(没有命中,默认)。

from collections import defaultdict
already_indexed = defaultdict(int)


def check_exist(small_list, default_list):
for item in small_list:
if default_list[item] == 1:
return True
return False


if check_exist(small_list, already_indexed):
continue
else:
for x in small_list:
already_indexed[x] = 1