私は Python にタプルのリストを持っています、そして、もしそのタプルがリストの中になければブランチを取ることを望む条件があります。 ifブランチ)
if curr_x -1 > 0 and (curr_x-1 , curr_y) not in myList:
# Do Something
これは私にとって実際にはうまくいきません。私は何をしましたか。
バグはおそらくあなたのコードのどこかにあるでしょう。
>>> 3 not in [2, 3, 4]
False
>>> 3 not in [4, 5, 6]
True
またはタプルを使って:
>>> (2, 3) not in [(2, 3), (5, 6), (9, 1)]
False
>>> (2, 3) not in [(2, 7), (7, 3), "hi"]
True
何かがPythonのリストに含まれている(含まれていない)かどうかをどうやって確認するのですか?
最も安くて読みやすい解決策は in
演算子(あるいはあなたの特定のケースではnot in
)を使うことです。ドキュメントに記載されているように、
演算子
in
とnot in
はメンバーシップをテストします。True
がx
のメンバーの場合はx in s
はs
と評価され、それ以外の場合はFalse
と評価されます。x not in s
はx in s
の否定を返します。
さらに、
演算子
not in
は、逆の真の値in
を持つように定義されています。
y not in x
は論理的にnot y in x
と同じです。
いくつか例を挙げます。
'a' in [1, 2, 3]
# False
'c' in ['a', 'b', 'c']
# True
'a' not in [1, 2, 3]
# True
'c' not in ['a', 'b', 'c']
# False
タプルはハッシュ可能なので(タプルも不変であるという事実の結果として)、これはタプルでも機能します。
(1, 2) in [(3, 4), (1, 2)]
# True
RHS上のオブジェクトが __contains__()
メソッドを定義している場合、ドキュメントの 比較 セクションの最後の段落で説明したように、in
は内部的にそれを呼び出します。
...
in
およびnot in
は、反復可能な型、または__contains__()
メソッドを実装する型によってサポートされています。例えば、あなたはこれをすることができます(しかしそうすべきではありません):
[3, 2, 1].__contains__(1)
# True
in
はショートサーキットなので、あなたの要素がリストの先頭にある場合、in
はより速く評価されます。
lst = list(range(10001))
%timeit 1 in lst
%timeit 10000 in lst # Expected to take longer time.
68.9 ns ± 0.613 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
178 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
項目がリストに含まれているかどうかを確認するだけでなく、それ以上のことをしたい場合は、次のような選択肢があります。
list.index
はアイテムのインデックスを取得するために使用できます。その要素が存在しない場合は、ValueError
が発生します。list.count
を使用できます。set
sを検討しましたか?あなた自身にこれらの質問をしてください:
hash
を呼ぶことができますか?これらの質問に「はい」と答えた場合は、代わりにset
を使用してください。 in
sのlist
メンバーシップテストは、O(n)時間計算量です。これは、pythonがあなたのリストを直線的にスキャンし、各要素を訪問し、それを検索項目と比較しなければならないことを意味します。これを繰り返し実行している場合、またはリストが大きい場合は、この操作によってオーバーヘッドが発生します。
一方、set
オブジェクトは、一定時間のメンバーシップチェックのためにそれらの値をハッシュします。チェックはin
を使っても行われます。
1 in {1, 2, 3}
# True
'a' not in {'a', 'b', 'c'}
# False
(1, 2) in {('a', 'c'), (1, 2)}
# True
あなたが探している/探していない要素があなたのリストの最後にあるというのが残念なことであれば、pythonはリストを最後までスキャンしたでしょう。これは以下のタイミングから明らかです。
l = list(range(100001))
s = set(l)
%timeit 100000 in l
%timeit 100000 in s
2.58 ms ± 58.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
101 ns ± 9.53 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
念のために言っておきますが、これはあなたが保存し検索している要素がハッシュ可能である限り適切なオプションです。さて、それらは不変の型か__hash__
を実装するオブジェクトでなければならないでしょう。