优雅的序列比较方法
Python有没有一种优雅的方式来检查不同类型的序列是否“相等”?下面这些方法可以用,但看起来对Python代码来说有点丑陋和冗长:
def comp1(a, b):
if len(a) != len(b):
return False
for i, v in enumerate(a):
if v != b[i]:
return False
return True
下面这个方法稍微短一点,但效率也低,因为它会创建一个第三个序列:
def comp2(a, b):
for l, r in map(None, a, b):
if l != r:
return False
return True
把这些例子强行塞进列表推导式也不是我想要的。
编辑:理想情况下,我希望找到一种在比较时不创建其他序列的解决方案。
8 个回答
9
除了创建临时列表或元组所占用的额外内存外,当不等式在序列的前面就出现时,这些答案在处理大序列时会比短路生成器的解决方案慢。
from itertools import starmap, izip
from operator import eq
all(starmap(eq, izip(x, y)))
或者说得更简洁一些
from itertools import imap
from operator import eq
all(imap(eq, x, y))
以下是一些来自ipython的基准测试结果
x=range(1000)
y=range(1000); y[10]=0
timeit tuple(x) == tuple(y)
100000 loops, best of 3: 16.9 us per loop
timeit all(imap(eq, x, y))
100000 loops, best of 3: 2.86 us per loop
13
你可以通过以下方法来判断两个可迭代对象(比如字符串、元组、列表,甚至是自定义的序列)是否相等,而不需要创建和存储重复的列表:
all(x == y for x, y in itertools.izip_longest(a, b))
需要注意的是,如果这两个可迭代对象的长度不一样,较短的那个会用 None
来填充。换句话说,它会把 [1, 2, None]
视为和 (1, 2)
相等。
补充:正如Kamil在评论中提到的,izip_longest
只在Python 2.6中可用。不过,这个函数的文档也提供了一个替代的实现,应该可以在2.3版本及更早的版本中使用。
补充 2:经过在几台不同的机器上测试,这种方法在某些情况下比 list(a) == list(b)
快,但我无法确定具体情况。大多数时候,它的速度大约是七倍慢。不过,我发现 tuple(a) == tuple(b)
的速度通常至少是 list
版本的两倍快。
19
把这两个序列都转换成列表,然后用内置的列表比较功能。这样做就足够了,除非你的序列特别大。
list(a) == list(b)
补充:
schickb 的测试显示,使用元组会稍微快一点:
tuple(a) == tuple(b)