如何检查下列项目之一是否在列表中?
- 2024-12-26 08:43:00
- admin 原创
- 55
问题描述:
除了编写函数之外,还有其他简便的方法来检查多个项目之一是否在列表中吗?
以下操作不起作用(预计True
两种情况下都会打印):
>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True
解决方案 1:
>>> 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,因此可以直接使用该值作为真值。
解决方案 2:
我正在考虑对Tobias 的解决方案进行以下细微的改动:
>>> a = [1,2,3,4]
>>> b = [2,7]
>>> any(x in a for x in b)
True
解决方案 3:
也许比较懒:
a = [1,2,3,4]
b = [2,7]
print any((True for x in a if x in b))
解决方案 4:
想想代码实际上说了什么!
>>> (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
。在第二个例子中,情况正好相反。这就是为什么它会根据它们的顺序返回不同的值。
解决方案 5:
a = {2,3,4}
if {1,2} & a:
pass
代码高尔夫版本。如果有意义,请考虑使用集合。我发现这比列表推导更具可读性。
解决方案 6:
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
解决方案 7:
我能想到的最好的办法是:
any([True for e in (1, 2) if e in a])
解决方案 8:
在 Python 3 中,我们可以开始使用解包星号。给定两个列表:
bool(len({*a} & {*b}))
解决方案 9:
当您想到“检查 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
始终快速的方法是制作一个集合(列表),但交集对于大型数据集最有效!
解决方案 10:
在某些情况下(例如唯一列表元素),可以使用集合运算。
>>> 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
>>>
解决方案 11:
我收集了其他答案和评论中提到的几种解决方案,然后进行了速度测试。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
',
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
',
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
',
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
',
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 &
',
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)
',
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)
',
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)
',
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)
',
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
解决方案 12:
有很多类似的答案,但对我来说,最简单,最干净的方法就是对两个集合进行逻辑与运算并将结果作为布尔值返回,我认为这一个尚未列出:
def check_for_matching_elements(list1, list2):
return bool(set(list1) & set(list2))
解决方案 13:
这将在一行中完成。
>>> a=[2,3,4]
>>> b=[1,2]
>>> bool(sum(map(lambda x: x in b, a)))
True
解决方案 14:
我不得不说,我的情况可能不是你想要的,但它可能为你的思维提供另一种选择。
我尝试过 set() 和 any() 方法,但速度仍然有问题。所以我想起 Raymond Hettinger 说过,Python 中的一切都是字典,尽可能使用 dict。所以我尝试了这种方法。
我使用带有 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
解决方案 15:
在 py3.11 上使用小数据集的一些计时:
from functools import reduce
to_match = [r for r in range(1, 50, 3_000)]
big_range = list(range(0, 100_000))
%timeit not set(to_match).isdisjoint(big_range)
120 ns ± 1.38 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
%timeit [item for item in to_match if item in big_range]
153 ns ± 0.775 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
%timeit len(set(to_match).intersection(big_range)) > 0
191 ns ± 2.13 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit any(map(lambda v: v in to_match, big_range))
235 ns ± 4.57 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit any(x in to_match for x in big_range)
419 ns ± 2.84 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit set(to_match) & set(big_range)
1.5 ms ± 13.3 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit reduce(lambda v1, v2: v1 or v2, map(lambda v: v in to_match, big_range))
7.27 ms ± 134 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
解决方案 16:
简单的。
_new_list = []
for item in a:
if item in b:
_new_list.append(item)
else:
pass
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件