优雅的序列比较方法

14 投票
8 回答
13865 浏览
提问于 2025-04-15 11:47

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)

撰写回答