回答:
>>> L1 = [2,3,4]
>>> L2 = [1,2]
>>> [i for i in L1 if i in L2]
[2]
>>> S1 = set(L1)
>>> S2 = set(L2)
>>> S1.intersection(S2)
set([2])
空のリストと空のセットはどちらもFalseであるため、値を真理値として直接使用できます。
any
とすぐに見つかったとして早期に返すことができるTrue
値を-それは、最初のリスト全体を構築する必要はありません
ああ、トビアス、私を倒した。私はあなたの解決策のこのわずかなバリエーションを考えていました:
>>> a = [1,2,3,4]
>>> b = [2,7]
>>> print(any(x in a for x in b))
True
x in long for x in short
vs x in short for x in long
)
a
とb
同じ長さで、最大と最小はなり左端のリスト、戻りますany()
呼び出しが両側に同じリスト上で動作します。長さのチェックが絶対に必要な場合は、2回目の呼び出しでリストの順序を逆にしますany(x in max(a, b, key=len) for x in (b, a, key=len))
。
any(x in max(a, b, key=len) for x in min(b, a, key=len))
分を逃した)。
多分もう少し怠惰:
a = [1,2,3,4]
b = [2,7]
print any((True for x in a if x in b))
any
早期に戻ることができるのではるかに高速ですが、バージョンではリストをany
使用する前に内包からリスト全体を構築する必要があります。二重括弧は不要であるため、@ user89788の答えは少し良いです
私が思いつくことができる最高の:
any([True for e in (1, 2) if e in a])
Python 3では、アスタリスクのアンパックを利用できるようになりました。2つのリストがあるとします。
bool(len({*a} & {*b}))
編集:アルカネンの提案を組み込む
「aがbかどうかを確認する」と考えるときは、ハッシュ(この場合はセット)を考えてください。最速の方法は、チェックしたいリストをハッシュし、そこにある各アイテムをチェックすることです。
これが、Joe Kobergの答えが速い理由です。集合交差のチェックは非常に高速です。
ただし、データがあまりない場合は、セットを作成するのは時間の無駄になります。したがって、リストのセットを作成し、各項目をチェックするだけです。
tocheck = [1,2] # items to check
a = [2,3,4] # the list
a = set(a) # convert to set (O(len(a)))
print [i for i in tocheck if i in a] # check items (O(len(tocheck)))
確認したい項目が少ない場合は、その差はごくわずかです。しかし、多数の数値を大きなリストと照合してください...
テスト:
from timeit import timeit
methods = ['''tocheck = [1,2] # items to check
a = [2,3,4] # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',
'''L1 = [2,3,4]
L2 = [1,2]
[i for i in L1 if i in L2]''',
'''S1 = set([2,3,4])
S2 = set([1,2])
S1.intersection(S2)''',
'''a = [1,2]
b = [2,3,4]
any(x in a for x in b)''']
for method in methods:
print timeit(method, number=10000)
print
methods = ['''tocheck = range(200,300) # items to check
a = range(2, 10000) # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',
'''L1 = range(2, 10000)
L2 = range(200,300)
[i for i in L1 if i in L2]''',
'''S1 = set(range(2, 10000))
S2 = set(range(200,300))
S1.intersection(S2)''',
'''a = range(200,300)
b = range(2, 10000)
any(x in a for x in b)''']
for method in methods:
print timeit(method, number=1000)
速度:
M1: 0.0170331001282 # make one set
M2: 0.0164539813995 # list comprehension
M3: 0.0286040306091 # set intersection
M4: 0.0305438041687 # any
M1: 0.49850320816 # make one set
M2: 25.2735087872 # list comprehension
M3: 0.466138124466 # set intersection
M4: 0.668627977371 # any
一貫して高速な方法は、(リストの)1つのセットを作成することですが、共通部分は大きなデータセットで最適に機能します。
場合によっては(たとえば、一意のリスト要素)、集合演算を使用できます。
>>> a=[2,3,4]
>>> set(a) - set([2,3]) != set(a)
True
>>>
または、set.isdisjoint()を使用して、
>>> not set(a).isdisjoint(set([2,3]))
True
>>> not set(a).isdisjoint(set([5,6]))
False
>>>
これは1行で実行されます。
>>> a=[2,3,4]
>>> b=[1,2]
>>> bool(sum(map(lambda x: x in b, a)))
True
他の回答やコメントで言及されている解決策のいくつかを収集してから、速度テストを実行しました。not set(a).isdisjoint(b)
が最速であることが判明しましたが、結果がであるときもそれほど遅くなりませんでしたFalse
。
3つの実行はそれぞれ、a
およびの可能な構成の小さなサンプルをテストしますb
。時間はマイクロ秒単位です。
Any with generator and max
2.093 1.997 7.879
Any with generator
0.907 0.692 2.337
Any with list
1.294 1.452 2.137
True in list
1.219 1.348 2.148
Set with &
1.364 1.749 1.412
Set intersection explcit set(b)
1.424 1.787 1.517
Set intersection implicit set(b)
0.964 1.298 0.976
Set isdisjoint explicit set(b)
1.062 1.094 1.241
Set isdisjoint implicit set(b)
0.622 0.621 0.753
import timeit
def printtimes(t):
print '{:.3f}'.format(t/10.0),
setup1 = 'a = range(10); b = range(9,15)'
setup2 = 'a = range(10); b = range(10)'
setup3 = 'a = range(10); b = range(10,20)'
print 'Any with generator and max\n\t',
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any(x in max(a,b,key=len) for x in min(b,a,key=len))',setup=setup3).timeit(10000000))
print
print 'Any with generator\n\t',
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any(i in a for i in b)',setup=setup3).timeit(10000000))
print
print 'Any with list\n\t',
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('any([i in a for i in b])',setup=setup3).timeit(10000000))
print
print 'True in list\n\t',
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('True in [i in a for i in b]',setup=setup3).timeit(10000000))
print
print 'Set with &\n\t',
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a) & set(b))',setup=setup3).timeit(10000000))
print
print 'Set intersection explcit set(b)\n\t',
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(set(b)))',setup=setup3).timeit(10000000))
print
print 'Set intersection implicit set(b)\n\t',
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('bool(set(a).intersection(b))',setup=setup3).timeit(10000000))
print
print 'Set isdisjoint explicit set(b)\n\t',
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup2).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(set(b))',setup=setup3).timeit(10000000))
print
print 'Set isdisjoint implicit set(b)\n\t',
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup1).timeit(10000000))
printtimes(timeit.Timer('not set(a).isdisjoint(b)',setup=setup3).timeit(10000000))
print
私の状況はあなたが探しているものではないかもしれませんが、それはあなたの考えの代替手段を提供するかもしれません。
set()メソッドとany()メソッドの両方を試しましたが、まだ速度に問題があります。だから私はレイモンド・ヘッティンガーがPythonのすべてが辞書であり、できる限りdictを使用すると言ったことを思い出しました。だから私はそれを試しました。
負の結果を示すためにintでdefaultdictを使用し、最初のリストの項目を2番目のリストのキーとして使用しました(defaultdictに変換)。dictを使用したインスタントルックアップがあるため、その項目がdefaultdictに存在するかどうかをすぐに知ることができます。2番目のリストのデータ構造を常に変更できるとは限りませんが、最初から変更できる場合は、はるかに高速です。list2(大きいリスト)をdefaultdictに変換する必要がある場合があります。ここで、keyは小さいリストから確認する潜在的な値であり、値は1(ヒット)または0(ヒットなし、デフォルト)です。
from collections import defaultdict
already_indexed = defaultdict(int)
def check_exist(small_list, default_list):
for item in small_list:
if default_list[item] == 1:
return True
return False
if check_exist(small_list, already_indexed):
continue
else:
for x in small_list:
already_indexed[x] = 1
a = [1, 2] b = [3, 5, 2, 6, 8, 9] c = [3, 5, 6, 8, 1, 9] print( (1 and 2) in b ,(2 and 1) in b ,(1 and 2) in c ,(2 and 1) in c, sep='\n')
is True False False True