【发布时间】:2010-10-18 22:11:12
【问题描述】:
我正在尝试找到一种简短的方法来查看以下任何项目是否在列表中,但我的第一次尝试不起作用。除了编写一个函数来实现这一点之外,还有一种简单的方法来检查多个项目中的一个是否在列表中。
>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True
【问题讨论】:
标签: python
我正在尝试找到一种简短的方法来查看以下任何项目是否在列表中,但我的第一次尝试不起作用。除了编写一个函数来实现这一点之外,还有一种简单的方法来检查多个项目中的一个是否在列表中。
>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True
【问题讨论】:
标签: python
啊,托拜厄斯,你打败了我。我在想your solution 的这种细微变化:
>>> a = [1,2,3,4]
>>> b = [2,7]
>>> any(x in a for x in b)
True
【讨论】:
x in long for x in short 与 x in short for x in long)
a 和b 两个列表长度相同,max 和min 将返回最左边的列表,这使得any() 调用操作双方的名单相同。如果您绝对需要检查长度,请在第二次调用中颠倒列表的顺序:any(x in max(a, b, key=len) for x in (b, a, key=len))。
any(x in max(a, b, key=len) for x in min(b, a, key=len))(错过了分钟)。
在 python 3 中,我们可以开始使用解包星号。给定两个列表:
bool(len({*a} & {*b}))
编辑:纳入 alkanen 的建议
【讨论】:
我不得不说,我的情况可能不是你想要的,但它可能会为你的想法提供另一种选择。
我已经尝试了 set() 和 any() 方法,但速度仍然存在问题。所以我记得 Raymond Hettinger 说过,python 中的一切都是字典,只要有可能就使用 dict。所以这就是我尝试的。
我使用带 int 的 defaultdict 来表示否定结果,并使用第一个列表中的项目作为第二个列表的键(转换为 defaultdict)。因为您可以使用 dict 即时查找,所以您可以立即知道该项目是否存在于 defaultdict 中。我知道您并不总是可以更改第二个列表的数据结构,但是如果您能够从一开始就更改,那么它会快得多。您可能必须将 list2(较大的列表)转换为 defaultdict,其中 key 是您要从小列表中检查的潜在值,值是 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
【讨论】:
我收集了其他答案和 cmets 中提到的几个解决方案,然后进行了速度测试。 not set(a).isdisjoint(b) 结果是最快的,结果是False 时也没有减慢多少。
三个运行中的每一个都测试a 和b 的可能配置的小样本。时间以微秒为单位。
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
【讨论】:
当您想到“检查 a 是否在 b 中”时,请考虑哈希(在本例中为集合)。最快的方法是对要检查的列表进行哈希处理,然后检查其中的每个项目。
这就是 Joe Koberg 的回答很快的原因:检查集合交集非常快。
当您没有大量数据时,制作集合可能会浪费时间。因此,您可以制作一组列表并检查每个项目:
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
始终快速的方法是制作(列表中的)一组,但交集在大型数据集上效果最好!
【讨论】:
简单。
_new_list = []
for item in a:
if item in b:
_new_list.append(item)
else:
pass
【讨论】:
a 是否在列表 b 中。
1 行没有列表推导。
>>> 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
【讨论】:
a = {2,3,4}
if {1,2} & a:
pass
代码高尔夫版本。如果这样做有意义,请考虑使用集合。 我发现这比列表理解更具可读性。
【讨论】:
也许更懒一点:
a = [1,2,3,4]
b = [2,7]
print any((True for x in a if x in b))
【讨论】:
any 可以提前返回,而您的版本必须在any 可以使用它之前从理解中构建整个列表。 @user89788 的回答稍微好一点,因为双括号是不必要的
这将在一行中完成。
>>> 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
>>>
【讨论】:
我能想到的最好的:
any([True for e in (1, 2) if e in a])
【讨论】:
想想代码实际上是怎么说的!
>>> (1 or 2)
1
>>> (2 or 1)
2
这应该可以解释。 :) Python 显然实现了“惰性或”,这不足为奇。它执行如下操作:
def or(x, y):
if x: return x
if y: return y
return False
在第一个示例中,x == 1 和 y == 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 值后立即返回 - 它不必先构建整个列表跨度>