Python:加速多列表中的匹配

Python:加速多列表中的匹配,python,performance,list,tuples,matching,Python,Performance,List,Tuples,Matching,我有四个类似的列表: L = [ (1,2), (3,5), (6,10), (7,8) ] M = [ (1,3), (8,9), (12,13) ] N = [ (6,10), (3,4), (5,6), (10,11), (12,13) ] T = [ (6,10) , (1,4) ] 我想检查L、M和N中T的每个元组是否存在: [[True, False, True], [False, False, False]] 下面的方法可以工作,但当T、L、M和N的大小增大时,效率会非常低 [

我有四个类似的列表:

L = [ (1,2), (3,5), (6,10), (7,8) ]
M = [ (1,3), (8,9), (12,13) ]
N = [ (6,10), (3,4), (5,6), (10,11), (12,13) ]
T = [ (6,10) , (1,4) ]
我想检查L、M和N中T的每个元组是否存在:

[[True, False, True], [False, False, False]]
下面的方法可以工作,但当T、L、M和N的大小增大时,效率会非常低

[[ y in x for x in [L, M, N] ] for y in T ]

对于大型列表,什么是最有效的加速方法?

列表中搜索时间与列表长度成正比。所以对于长名单来说,这是很高的。有专门为搜索而优化的数据结构。python中最简单的是
set
。它计算每个元素的散列(因此元素必须是可散列的,整数元组是可以的)。 然后你做同样的检查。所以你只需要添加

L = set(L)
M = set(M)
N = set(N)
作为副作用,您将失去列表中元素的顺序。如果存在非唯一值,它们将合并为一个

关于提速的更新:


如果搜索值在最开始时,则在
列表中搜索的时间可能很长。但如果不是这样的话,
set
应该快得多,因为搜索时间与日志(len(数据))成正比。
列表
的最坏情况是
列表
中没有搜索的项目,因此需要检查每个项目。在这种情况下,在1M
list
中搜索要比在
set
中搜索慢200K(刚刚在python3中选中)

list
中搜索时间与列表长度成正比。所以对于长名单来说,这是很高的。有专门为搜索而优化的数据结构。python中最简单的是
set
。它计算每个元素的散列(因此元素必须是可散列的,整数元组是可以的)。 然后你做同样的检查。所以你只需要添加

L = set(L)
M = set(M)
N = set(N)
作为副作用,您将失去列表中元素的顺序。如果存在非唯一值,它们将合并为一个

关于提速的更新:


如果搜索值在最开始时,则在
列表中搜索的时间可能很长。但如果不是这样的话,
set
应该快得多,因为搜索时间与日志(len(数据))成正比。
列表
的最坏情况是
列表
中没有搜索的项目,因此需要检查每个项目。在这种情况下,在1M
list
中搜索要比在
set
(刚刚在python3中选中)中搜索慢200K

您还可以考虑使用Numpy数组而不是普通的python列表和元组。 看 因为你必须检查列表中的每个元素,总的速度总是线性的,所以你必须使用一个更快的实现,比如NUMPY,或者用一个更快的语言扩展你的代码,比如Rust,C,C++。
使用
np.asarray(listname)
函数对其进行转换

您还可以研究使用Numpy数组而不是普通的python列表和元组。 看 因为你必须检查列表中的每个元素,总的速度总是线性的,所以你必须使用一个更快的实现,比如NUMPY,或者用一个更快的语言扩展你的代码,比如Rust,C,C++。
使用
np.asarray(listname)
函数对其进行转换

使用字典并比较这些值

LMNT = {'L':[(1,2),(3,5),(6,10),(7,8)],
'M':[(1,3),(8,9),(12,13)],
'N':[ (6,10), (3,4), (5,6), (10,11), (12,13) ],
'T':[ (6,10) , (1,4) ]}
然后你可以比较字典。
LMNT['M'][0][1]
值为2


LMNT['N'][4]
值是
(12,13)

使用字典并比较这些值

LMNT = {'L':[(1,2),(3,5),(6,10),(7,8)],
'M':[(1,3),(8,9),(12,13)],
'N':[ (6,10), (3,4), (5,6), (10,11), (12,13) ],
'T':[ (6,10) , (1,4) ]}
然后你可以比较字典。
LMNT['M'][0][1]
值为2


LMNT['N'][4]
值为
(12,13)
如果可以处理不同的输出格式,也可以设置交叉点

>>> L = set([ (1,2), (3,5), (6,10), (7,8) ])
>>> M = set([ (1,3), (8,9), (12,13) ])
>>> N = set([ (6,10), (3,4), (5,6), (10,11), (12,13) ])
>>> T = set([ (6,10) , (1,4) ])
>>> [T & x for x in (L,M,N)]
[{(6, 10)}, set(), {(6, 10)}]

这将为您提供一组元组列表,这些元组分别出现在两个集合中。这应该比使用嵌套循环更快。

如果可以处理不同的输出格式,也可以设置交叉点

>>> L = set([ (1,2), (3,5), (6,10), (7,8) ])
>>> M = set([ (1,3), (8,9), (12,13) ])
>>> N = set([ (6,10), (3,4), (5,6), (10,11), (12,13) ])
>>> T = set([ (6,10) , (1,4) ])
>>> [T & x for x in (L,M,N)]
[{(6, 10)}, set(), {(6, 10)}]

这将为您提供一组元组列表,这些元组分别出现在两个集合中。这应该比使用嵌套循环更快。

…这样在不改变主要算法的情况下,速度会提高30%。@ForceBru对于涉及的大型集合/列表,这应该是一个更显著的改进。你从哪里得到这个号码的?@schwobasegll,我也这么认为<代码>设置
s太棒了!我刚刚在我的机器上测试了这个。我刚刚测试了1M值的列表,set比list快了大约100倍……这将在没有重大算法更改的情况下提供30%的加速。@ForceBru对于大型涉及的集合/列表,这应该是一个更显著的改进。你从哪里得到这个号码的?@schwobasegll,我也这么认为<代码>设置
s太棒了!我刚刚在我的机器上测试了这个。我刚刚测试了1M值的列表,set比list快100倍。这将比OP的原始代码效率低。现在需要更长的时间,因为列表仍然是列表,但需要额外的字典查找成本。这将比OP的原始代码效率低。现在需要更长的时间,因为列表仍然是列表,但需要额外的字典查找成本。