在Python中,找出两个有序列表之间的差异数量

12

我想要比较两个长度相同的列表

a = [1, 3, 5, 7, 9]
b = [1, 2, 5, 7, 3]

找出两个字符串之间的不同字符数n,在这种情况下n = 2,如果长度不相等则返回错误。有什么符合Python风格的方法吗?

3个回答

21

最简单的方法是使用sum()内置函数生成器表达式

def differences(a, b):
    if len(a) != len(b):
        raise ValueError("Lists of different length.")
    return sum(i != j for i, j in zip(a, b))

我们使用zip()循环遍历列表,然后进行比较。由于True == 1False == 0,所以我们只需对它们进行求和即可得到差异数。另一种选择是使用生成器表达式的条件部分:

sum(1 for i, j in zip(a, b) if i != j)

我无法确定哪种更易读,也怀疑它们之间是否存在性能差异。


我更喜欢显式的 1 for i,而不是隐式布尔值(依赖于它是一个 int),但无论如何 +1(只要长度检查是显式的)。 - Jon Clements
@JonClements 我同意,但是重要的部分(比较)被推到了表达式的末尾,感觉很奇怪。我一直在改变自己的想法,不知道哪个更好。 - Gareth Latty

1

一行代码解决方案,如果长度不相等还会产生错误:

>>> sum(map(lambda x,y: bool(x-y),a,b))
2

现在尝试输入不同长度的内容:
>>> sum(map(lambda x,y: bool(x-y),[1,2],[1]))
TypeError

如何工作:bool(x,y)返回True,如果元素不同。然后我们将此函数映射到2个列表上,并得到列表[False,True,False,True,False]。
如果我们将不同长度的列表放入函数map()中,则会得到TypeError错误。
最后,这个布尔列表的sum()函数结果为2。

请注意,map()lambda通常比列表推导式/生成器表达式更慢且不易读取,并且仅适用于数字。 - Gareth Latty
是的,它们速度较慢,但代码更短,这取决于需要什么(夸张地说,在需要速度的情况下,不要使用Python :))。可读性是一个非常主观的问题。你是对的,这在未定义“-”操作的类型上不起作用。 - Max Li
感谢提供另一种解决方案。我更喜欢@Lattyware的解决方案,因为我个人认为它更易读。我不熟悉lambda函数。此外,使用他的解决方案,我可以定义错误消息,以便知道出现了什么错误。 - LWZ

-2
你可以使用集合。将两个转换为集合,然后找到它们之间的差异。例如:
>>> a = [1,3,5,7,9]
>>> b = [1,2,5,7,2]
>>> len(set(a) -  set(b))
2

这可以被封装在一个函数中,首先检查长度差异。

2
如果有重复元素,这种方法就行不通了,并且它也不考虑顺序。例如 difference([1, 3, 5, 7, 9], [9, 7, 5, 3, 1]) 的结果是 0 而不是 4。原帖中的例子将 3 计为不同的元素,尽管它在两个列表中都存在(也就是说,位置很重要)。此外,这种方法也忽略了列表长度可能不同的情况,正如问题中所提到的。 - Gareth Latty
啊,是的,我错过了最后一个3,并在我的示例中使用了2。我的错!我提到了一个函数可以用来检查差异,就像你的示例代码一样。 - user2079098

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接