同じ長さの 2 つのリストがある場合、これらのリストの対応する要素が等しくない最初の位置を効率的に見つけるにはどうすればよいでしょうか? 基本的に、インデックスまたは 2 つの等しくない要素のいずれかが必要です。
リストに対する明らかな明示的な反復なしで、簡潔な「pythonic」ソリューションが存在するかどうかに興味があります。
リストの反復を避けることはできませんが、理解を深めて洗練された解決策を得ることができます。
next( (idx, x, y) for idx, (x, y) in enumerate(zip(list1, list2)) if x!=y )
1行中心ではないものが好きなら、このように分割できます
coupled_idx = enumerate(zip(list1, list2))
res = next( idx for idx, (x, y) in coupled_idx if x!=y )
編集:
さらに、2 つのリストが完全に等しい場合を確認する必要がある場合は、次の関数に 2 番目のパラメーターを追加して、インデックスが見つからない場合に何を返すかを指定できます。最も一般的なオプションは None を返すことです:
coupled_idx = enumerate(zip(list1, list2))
res = next( (idx for idx, (x, y) in coupled_idx if x!=y), None )
この呼び出しの関数の唯一の引数ではないため、ジェネレーター式を括弧で囲む必要があることに注意してください。
ちょっとした楽しみを加えるために、式を連鎖させて n 番目の異なるカップルに尋ねることもできます。たとえば、これにより、5 つ目までのすべてのカップルが得られます (カップルが欠落している場合は [なし] で埋められます)。
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関数を介して特定のソリューションのみを選択できます
>>> from operator import eq
>>> a = [1, 2, 4, 3]
>>> b = [1, 2, 3, 4]
>>> map(eq, a, b).index(False)
2
>>> 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)
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