次の項目のいずれかがリストにあるかどうかを確認するにはどうすればよいですか?


220

次の項目のいずれかがリストに含まれているかどうかを確認する簡単な方法を見つけようとしていますが、最初の試みは機能しません。これを達成するための関数を記述する以外に、複数の項目の1つがリストにあるかどうかを確認する簡単な方法があります。

>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True

おかしいことに、私は「そして」がどのように動作するかを確認しました。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
Piotr Kamoda

回答:


266
>>> 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であるため、値を真理値として直接使用できます。


6
交差点のアイデアは私にこのアイデアを与えました。return len(set(a).intersection(set(b)))
Deon

13
FWIW-私は速度比較を行いました、そしてここで提供された最初の解決策は断食されました。
jackiekazil

2
ので、発電機を使用して、@ user89788の答えは、再びはるかに高速であるanyとすぐに見つかったとして早期に返すことができるTrue値を-それは、最初のリスト全体を構築する必要はありません
Anentropic

リストに重複がある場合、2番目のセットのセットは機能しません(セットには各アイテムの1つしか含まれていないため)。`L1 = [1,1,2,3] 'および' L2 = [1,2,3] 'の場合、すべてのアイテムが交差していることがわかります。
donrondadon 2018

私はこれがほぼ10年前のものであることを知っていますが、最初の解決策はうまくいかないようです。文字列をL2の数値に置き換えたところ、次のエラーが発生しました:TypeError: 'in <string>'は、リストではなく左オペランドとして文字列が必要です
roastbeeef

227

ああ、トビアス、私を倒した。私はあなたの解決策のこのわずかなバリエーションを考えていました:

>>> a = [1,2,3,4]
>>> b = [2,7]
>>> print(any(x in a for x in b))
True

5
これは非常に古い答えだと思いますが、一方のリストが非常に長く、もう一方のリストが短い場合、パフォーマンスが速くなる順序がありますか?(つまり、x in long for x in shortvs x in short for x in long
ルークサパン

11
@LukeSapan:あなたは正しいです。その順序は、「print any(x in max(a、b、key = len)for x in min(a、b、key = len))」を介して取得できます。これは、x in longに対してx in longを使用します。
Nuclearman 2014

2
これはジェネレータを使用しており、一致が見つかるとすぐに戻るため、これが最良の回答です(他の人が言ったように、この回答ではありません!)。
dotcomly 2016

4
@Nuclearman、気を付ける:二つのリスト場合ab同じ長さで、最大と最小はなり左端のリスト、戻りますany()呼び出しが両側に同じリスト上で動作します。長さのチェックが絶対に必要な場合は、2回目の呼び出しでリストの順序を逆にしますany(x in max(a, b, key=len) for x in (b, a, key=len))
ノアボガート

3
@NoahBogartあなたは正しいですし、その解決策はどれも同じくらい良いようです。私はまたあなたが意味したと思います:(any(x in max(a, b, key=len) for x in min(b, a, key=len))分を逃した)。
Nuclearman 2017年

29

多分もう少し怠惰:

a = [1,2,3,4]
b = [2,7]

print any((True for x in a if x in b))

1
私が投稿したものとほぼ同じです。
BastienLéonard09年

5
@BastienLéonard...ただし、ジェネレータを使用しているためany早期に戻ることができるのではるかに高速ですが、バージョンではリストをany使用する前に内包からリスト全体を構築する必要があります。二重括弧は不要であるため、@ user89788の答えは少し良いです
Anentropic

17

コードが実際に言っていることを考えてください!

>>> (1 or 2)
1
>>> (2 or 1)
2

それはおそらくそれを説明するはずです。:) Pythonは明らかに「レイジーOR」を実装していますが、これは驚くことではありません。これは次のように実行されます。

def or(x, y):
    if x: return x
    if y: return y
    return False

最初の例では、x == 1y == 2。2番目の例では、その逆です。そのため、それらの順序に応じて異なる値を返します。


16
a = {2,3,4}
if {1,2} & a:
    pass

コードゴルフ版。意味がある場合は、セットの使用を検討してください。これはリスト内包よりも読みやすいと思います。


12

リスト内包表記のない1行。

>>> any(map(lambda each: each in [2,3,4], [1,2]))
True
>>> any(map(lambda each: each in [2,3,4], [1,5]))
False
>>> any(map(lambda each: each in [2,3,4], [2,4]))
True


6

Python 3では、アスタリスクのアンパックを利用できるようになりました。2つのリストがあるとします。

bool(len({*a} & {*b}))

編集:アルカネンの提案を組み込む


1
@Anthonyは、aの要素を含むセットとbの要素を含む別のセットを作成し、それらのセットの間の共通部分(共有要素)を見つけ、any()は、真実であるような要素がある場合にtrueを返します。唯一の共有要素が偽造(数値0など)である場合、ソリューションは機能しません。any()よりもlen()を使用する方がよい場合があります
alkanen

1
@alkanenグッドコール
Daniel Braun

なぜset関数を使わないのですか?
Alex78191

5

「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つのセットを作成することですが、共通部分は大きなデータセットで最適に機能します。


3

場合によっては(たとえば、一意のリスト要素)、集合演算を使用できます。

>>> 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
>>> 

2

これは1行で実行されます。

>>> a=[2,3,4]
>>> b=[1,2]
>>> bool(sum(map(lambda x: x in b, a)))
True

ここではTrueになりません>>> print a [2、3、4] >>> print b [2、7] >>> reduce(lambda x、y:x in b、a)False
Deon

うん。あなたが正しい。reduce()は、私が思っていた方法でブール値を処理していませんでした。上で書いた改訂版は、その場合でも機能します。
Chris Upchurch、

2

他の回答やコメントで言及されている解決策のいくつかを収集してから、速度テストを実行しました。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

0

私の状況はあなたが探しているものではないかもしれませんが、それはあなたの考えの代替手段を提供するかもしれません。

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

-4

シンプル。

_new_list = []
for item in a:
    if item in b:
        _new_list.append(item)
    else:
        pass

1
これは質問の答えにはなりません。OP は、リストの値がリスト にあるかどうを知りたいと考えていaますb
That1Guy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.