比较序列的优雅方式

sch*_*ckb 11 python

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
Run Code Online (Sandbox Code Playgroud)

由于创建了第三个序列,以下内容有点短,但效率也较低:

def comp2(a, b):
    for l, r in map(None, a, b):
        if l != r:
            return False
    return True
Run Code Online (Sandbox Code Playgroud)

将其中一个例子列入列表理解并不是我正在寻找的.

编辑:理想情况下,我正在寻找一种在比较期间不会创建另一个序列的解决方案.

Aym*_*ieh 17

将两个序列转换为列表,并使用内置列表比较.它应该足够了,除非你的序列非常大.

list(a) == list(b)
Run Code Online (Sandbox Code Playgroud)

编辑:

schickb完成的测试显示使用元组稍快一些:

tuple(a) == tuple(b)
Run Code Online (Sandbox Code Playgroud)

  • 这将创建两个附加列表。由于列表可能很长,我想避免这种情况。 (2认同)
  • @schickb:我们谈论多久了?根据您帖子的标题和第一句话,将优雅作为首要任务,效率作为奖励是公平的.对我来说,转换为(新)列表是迄今为止最优雅,最"程序员效率"的解决方案. (2认同)

Ben*_*ank 12

您可以使用以下方法确定任何两个迭代(字符串,元组,列表,甚至自定义序列)的相等性,而无需创建和存储重复列表:

all(x == y for x, y in itertools.izip_longest(a, b))
Run Code Online (Sandbox Code Playgroud)

请注意,如果两个迭代的长度不同,则较短的一个将用Nones 填充.换句话说,它将被视为[1, 2, None]等于(1, 2).

编辑:正如卡米尔在评论中指出的那样,izip_longest仅在Python 2.6中提供.但是,该函数的文档还提供了一个替代实现,它应该一直工作回2.3.

编辑2:在几台不同的机器上测试后,看起来这只比list(a) == list(b)某些情况下更快,我无法隔离.大多数情况下,它需要大约七倍的时间.但是,我发现tuple(a) == tuple(b)一直至少是该list版本的两倍.


Joh*_*ooy 5

除了创建临时列表/元组所使用的额外内存之外,当序列中的早期不等式发生时,这些答案将丢失给大序列的短路生成器解决方案

from itertools import starmap, izip
from operator import eq
all(starmap(eq, izip(x, y)))
Run Code Online (Sandbox Code Playgroud)

或者更简洁

from itertools import imap
from operator import eq
all(imap(eq, x, y))
Run Code Online (Sandbox Code Playgroud)

来自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
Run Code Online (Sandbox Code Playgroud)