Python:找到两个列表中的第一个不匹配

时间:2013-04-05 09:43:30

标签: python list

鉴于两个长度相同的列表,如何有效地找到这些列表的相应元素不相等的第一个位置?基本上我需要索引或两个不相等的元素。

我很感兴趣是否存在一些简洁的“pythonic”解决方案,而且没有对列表进行明显的显式迭代。

6 个答案:

答案 0 :(得分:4)

您无法避免对列表进行迭代,但您可以通过理解来实现并获得优雅的解决方案:

next( (idx, x, y) for idx, (x, y) in enumerate(zip(list1, list2)) if x!=y )

如果你喜欢不那么以一行为中心的东西,你可以像这样分开它

coupled_idx = enumerate(zip(list1, list2))
res = next( idx for idx, (x, y) in coupled_idx if x!=y )

编辑:

作为补充,如果你需要检查两个列表可以完全相等的情况,你可以在下一个函数中添加第二个参数,告诉它如果没有找到索引则返回什么。最常见的选择是返回None:

coupled_idx = enumerate(zip(list1, list2))
res = next( (idx for idx, (x, y) in coupled_idx if x!=y), None )

请注意,您需要将括号内的生成器表达式括起来,因为它不是此调用中函数的唯一参数。

只是为了增加一点乐趣,你也可以通过链接表达式来询问第n个不同的情侣。例如,这会给你所有的夫妻直到第五个夫妇(如果夫妇失踪则填写无)

coupled_idx = enumerate(zip(list1, list2))
coupler = (idx for idx, (x, y) in coupled_idx if x!=y)
res = [ next(coupler, None) for _ in range(5) ]

EDIT2:

这种解决方案实际上通过zip函数创建了两个列表的副本。如果您需要避免这种情况,您可以使用itertools模块中的 izip 功能。

关于有趣的部分,您可以通过 islice 功能从同一模块中选择某些解决方案

答案 1 :(得分:2)

>>> from operator import eq
>>> a = [1, 2, 4, 3]
>>> b = [1, 2, 3, 4]
>>> map(eq, a, b).index(False)
2

答案 2 :(得分:1)

>>> from itertools import dropwhile
>>> a = [1, 2, 4, 3]
>>> b = [1, 2, 3, 4]
>>> next(dropwhile(lambda x: x[0] == x[1], zip(a, b)))
(4, 3)

答案 3 :(得分:0)

In [1]: l1=[1,2,3]

In [2]: l2=[1,4,5]

In [4]: next(i for i, (el1, el2) in enumerate(zip(l1, l2)) if el1 != el2)
Out[4]: 1

此处,1l1l2不同的第一个索引。

答案 4 :(得分:0)

试试这个:

next(i for i, (el1,el2) in enumerate(zip(li1,li2)) if el1 != el2)

或者它的等效功能:

def first_diff(li1, li2):
    for i, (el1,el2) in enumerate(zip(li1,li2)):
        if el1 != el2:
            return i
    return False

一个例子

>>> li1 = range(32)
>>> li2 = range(32)
>>> li2[10] = 2
>>> next(i for i, (el1,el2) in enumerate(zip(li1,li2)) if el1 != el2)
10
>>> first_diff(li1, li2)
10

答案 5 :(得分:0)

同时,在下一个命令中允许使用额外的默认参数。由于filter和zip是生成器,因此以下构造触摸两个列表中最少数量的元素以确定第一个值,其中两个列表均在同一索引处定义但在该索引处具有不同值,或者在不存在此类值时返回默认值。

只要可以找到差异,就返回不同的值:

a=[1,2,3,4,5,6]

b=[1,2,7,4,'Hugo']

next(filter(lambda x: x[0]!=x[1], zip(a,b)),"Value that you choose to represent failure")

Out[91]: (3, 7)

当两个列表相等时,将返回默认值:

b[2]=3; b[4]=5; b.append(6)

next(filter(lambda x: x[0]!=x[1], zip(a,b)),"Value that you choose to represent failure")

Out[93]: 'Value that you choose to represent failure'

任何其他问题导致搜索失败时,将返回默认值:

a=[]

next(filter(lambda x: x[0]!=x[1], zip(a,b)),"Value that you choose to represent failure")

Out[95]: 'Value that you choose to represent failure'

当然,您可以将生成器分配给变量,然后重复使用next来查找第二个或其他事件。

a=[1,2]

b=['fred',1,2.2]

f=filter(lambda x: x[0]!=x[1], zip(a,b))

next(f,'error')

Out[110]: (1, 'fred')

next(f,'error')

Out[111]: (2, 1)

next(f,'error')

Out[112]: 'error'

您可以将None设置为默认值,以静默失败或用于测试

next(f,None)

从列表末尾掉下来的后续调用不会引发异常或错误。

next(f,'No more')

Out[114]: 'No more'