簡単な答え:使用してくださいnot set(a).isdisjoint(b)、それは一般的に最速です。
2つのリストがaありb、アイテムを共有しているかどうかをテストする一般的な方法は4つあります。最初のオプションは、両方をセットに変換し、それらの交差をチェックすることです。
bool(set(a) & set(b))
セットはPythonのハッシュテーブルを使用して保存されるO(1)ため、それらを検索することは可能です(Pythonの演算子の複雑さの詳細については、ここを参照してください)。理論的には、これはリストとのオブジェクトのO(n+m)平均です。ただし、1)最初にリストからセットを作成する必要があります。これには無視できない時間がかかる可能性があります。2)ハッシュの衝突がデータ間でまばらであると想定しています。nmab
これを行う2番目の方法は、次のようなリストで反復を実行するジェネレータ式を使用することです。
any(i in a for i in b)
これにより、インプレース検索が可能になるため、中間変数に新しいメモリが割り当てられることはありません。それはまた、最初の発見で保釈されます。ただし、in演算子は常にO(n)リストにあります(ここを参照)。
別の提案されたオプションは、次のように、リストの1つを反復処理し、セット内のもう1つを変換して、このセットのメンバーシップをテストするハイブリッドです。
a = set(a); any(i in a for i in b)
4番目のアプローチはisdisjoint()、(凍結された)セットの方法(ここを参照)を利用することです。次に例を示します。
not set(a).isdisjoint(b)
検索する要素が配列の先頭近くにある場合(たとえば、並べ替えられている場合)、集合の共通部分メソッドは中間変数に新しいメモリを割り当てる必要があるため、ジェネレータ式が優先されます。
from timeit import timeit
>>> timeit('bool(set(a) & set(b))', setup="a=list(range(1000));b=list(range(1000))", number=100000)
26.077727576019242
>>> timeit('any(i in a for i in b)', setup="a=list(range(1000));b=list(range(1000))", number=100000)
0.16220548999262974
これは、リストサイズの関数でのこの例の実行時間のグラフです。

両方の軸が対数であることに注意してください。これは、ジェネレータ式の最良のケースを表しています。ご覧のとおり、このisdisjoint()方法はリストサイズが非常に小さい場合に適していますが、ジェネレータ式はリストサイズが大きい場合に適しています。
一方、検索はハイブリッド式とジェネレーター式の最初から始まるため、共有要素が体系的に配列の最後にある場合(または両方のリストが値を共有しない場合)、互いに素で設定された交差アプローチは次のようになります。ジェネレータ式やハイブリッドアプローチよりもはるかに高速です。
>>> timeit('any(i in a for i in b)', setup="a=list(range(1000));b=[x+998 for x in range(999,0,-1)]", number=1000))
13.739536046981812
>>> timeit('bool(set(a) & set(b))', setup="a=list(range(1000));b=[x+998 for x in range(999,0,-1)]", number=1000))
0.08102107048034668

リストのサイズが大きいほど、ジェネレータ式の速度が大幅に低下することに注意してください。これは、前の図の100000ではなく、1000回の繰り返しのみです。この設定は、要素が共有されていない場合にもよく近似し、互いに素で設定された交差アプローチの最良のケースです。
乱数を使用した2つの分析を次に示します(いずれかの手法を優先するようにセットアップを調整する代わりに)。

共有の可能性が高い:要素はからランダムに取得され[1, 2*len(a)]ます。共有の可能性が低い:要素はからランダムに取得され[1, 1000*len(a)]ます。
これまで、この分析では、両方のリストが同じサイズであると想定していました。サイズの異なる2つのリストの場合、たとえば、aはるかに小さい場合isdisjoint()は、常に高速です。

リストが小さいことを確認してくださいa。小さいほど、パフォーマンスが低下します。この実験では、aリストサイズをに一定に設定しました5。
要約すれば:
- リストが非常に小さい場合(<10要素)、
not set(a).isdisjoint(b)常に最速です。
- リスト内の要素がソートされているか、利用できる規則的な構造を持っている場合、ジェネレータ式
any(i in a for i in b)は大きなリストサイズで最速です。
- で設定された共通部分をテストします。
not set(a).isdisjoint(b)これは常に。よりも高速ですbool(set(a) & set(b))。
- ハイブリッドの「リストを反復処理し、セットでテストする」
a = set(a); any(i in a for i in b)は、一般に他の方法よりも低速です。
- ジェネレータ式とハイブリッドは、要素を共有しないリストに関しては、他の2つのアプローチよりもはるかに低速です。
ほとんどの場合、isdisjoint()要素が共有されていない場合は非常に非効率的であるため、ジェネレータ式の実行にはるかに長い時間がかかるため、このメソッドを使用するのが最善のアプローチです。