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

2024-12-26 08:43:00
admin
原创
55
摘要:问题描述:除了编写函数之外,还有其他简便的方法来检查多个项目之一是否在列表中吗?以下操作不起作用(预计True两种情况下都会打印):>>> a = [2,3,4] >>> print (1 or 2) in a False >>> print (2 or ...

问题描述:

除了编写函数之外,还有其他简便的方法来检查多个项目之一是否在列表中吗?

以下操作不起作用(预计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 == 1y == 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

三次运行中,每次都测试和的可能配置的一小部分样本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
    ',
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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   984  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   0  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   0  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   0  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用