python - 在 2 个 python 列表的开头查找公共(public)元素的最快方法?

标签 python list

在两个 python 列表的开头找到共同元素的最快方法是什么?我使用 for 循环对其进行了编码,但我认为使用列表理解来编写它会更快……不幸的是,我不知道如何中断列表理解。这是我写的代码:

import datetime

list1=[1,2,3,4,5,6]
list2=[1,2,4,3,5,6]

#This is the "for loop" version, and takes about 60 ms on my machine
start=datetime.datetime.now()
out=[]
    for (e1, e2) in zip(list1, list2):
    if e1 == e2:
        out.append(e1)
    else:
        break
end=datetime.datetime.now()
print out
print "Execution time: %s ms" % (float((end - start).microseconds) / 1000)

#This is the list-comprehension version, it takes about 15 ms to run,
#but unfortunately returns the wrong result because I can't break the loop.
start=datetime.datetime.now()
out = [ e1 for (e1, e2) in zip(list1, list2) if e1 == e2 ]
end=datetime.datetime.now()
print out
print "Execution time: %s ms" % (float((end - start).microseconds) / 1000)

是否也有没有列表理解的好的解决方案?

最佳答案

>>> from operator import ne
>>> from itertools import count, imap, compress
>>> list1[:next(compress(count(), imap(ne, list1, list2)), 0)]
[1, 2]

时间:

from itertools import *
from operator import ne

def f1(list1, list2, enumerate=enumerate, izip=izip):
    out = []
    out_append = out.append
    for e1, e2 in izip(list1, list2):
        if e1 == e2:
            out_append(e1)
        else:
            break
    return out

def f2(list1, list2, list=list, takewhile=takewhile, izip=izip):
    return [i for i, j in takewhile(lambda (i,j):i==j, izip(list1, list2))]

def f3(list1, list2, next=next, compress=compress, count=count, imap=imap,
       ne=ne):
    return list1[:next(compress(count(), imap(ne, list1, list2)), 0)]

def f4(list1, list2):
    out = []
    out_append = out.append
    i = 0
    end = min(len(list1), len(list2))
    while i < end and list1[i]==list2[i]:
        out_append(list1[i])
        i+=1
    return out

def f5(list1, list2, len=len, enumerate=enumerate):
    if len(list1) > len(list2):
        list1, list2 = list2, list1
    for i, e in enumerate(list1):
        if list2[i] != e:
            return list1[:i]
    return list1[:]

def f6(list1, list2, enumerate=enumerate):
    result = []
    append = result.append
    for i,e in enumerate(list1):
        if list2[i] == e:
            append(e)
            continue
        break
    return result


from timeit import timeit
list1 =[1,2,3,4,5,6];list2=[1,2,4,3,5,6]
sol = f3(list1, list2)

for func in 'f1', 'f2', 'f3', 'f4', 'f5', 'f6':
    assert eval(func + '(list1, list2)') == sol, func + " produces incorrect results"
    print func
    print timeit(stmt=func + "(list1, list2)", setup='from __main__ import *')

f1
1.52226996422
f2
2.44811987877
f3
2.04677891731
f4
1.57675600052
f5
1.6997590065
f6
1.71103715897

list1=[1]*100000+[1,2,3,4,5,6]; list2=[1]*100000+[1,2,4,3,5,6] with timeit 自定义为 100 计时,timeit (stmt=func + "(list1, list2)", setup='from __main__ import list1, list2, f1,f2,f3,f4', number=1000)

f1
14.5194740295
f2
29.8510630131
f3
12.6024291515
f4
24.465034008
f5
12.1111371517
f6
16.6644029617

所以@ThijsvanDien 的这个解决方案是最快的,紧随其后,但我仍然喜欢它的功能风格;)


但是 numpy 总是赢(你应该总是使用 numpy 这样的事情)

>>> import numpy as np
>>> a, b = np.array([1,2,3,4,5,6]), np.array([1,2,4,3,5,6])
>>> def f8(a, b, nonzero=np.nonzero):
        return a[:nonzero(a!=b)[0][0]]

>>> f8(a, b)
array([1, 2])
>>> timeit(stmt="f8(a, b)", setup='from __main__ import *')
6.50727105140686
>>> a, b = np.array([1]*100000+[1,2,3,4,5,6]), np.array([1]*100000+[1,2,4,3,5,6])
>>> timeit(stmt="f8(a, b)", setup='from __main__ import *', number=1000)
0.7565150260925293

可能有一个更快的 numpy 解决方案,但这表明它有多快。

关于python - 在 2 个 python 列表的开头查找公共(public)元素的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16646062/

相关文章:

C++ - 推回队列列表

python - tensorflow 简单逻辑回归

android - onListItemClick 回调未激活

Perl,获取所有哈希值

python - 随机数重新排序的总和组合成重复值

python - 我如何获得两个相同的python列表的元素?

python - 如何从python列表的每个元素中删除前缀?

python - Tkinter 中的 tcl 错误

python - mypy 提示扩展基类的属性类型

python - 在 bash 脚本中调用 python 脚本会更改变量的类型