鉴于两个长度相同的列表,如何有效地找到这些列表的相应元素不相等的第一个位置?基本上我需要索引或两个不相等的元素。
我很感兴趣是否存在一些简洁的“pythonic”解决方案,而且没有对列表进行明显的显式迭代。
答案 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
此处,1
是l1
和l2
不同的第一个索引。
答案 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'