Python | データ構造:in / not in

Python
スポンサーリンク

概要(in / not in は「含まれるか」を判定する所属検査演算子)

in / not in は、ある値がリスト・タプル・文字列・セット・辞書などの「中に含まれているか」を真偽値で返す演算子です。in は含まれていれば True、not in は含まれていなければ True(in の否定)になります。文字列では「部分文字列として含まれるか」を判定できるのが直感的で便利です。

fruits = ["apple", "banana", "orange"]
print("apple" in fruits)       # True
print("grape" not in fruits)   # True

text = "Hello, world!"
print("Hello" in text)         # True(部分一致)
print("hello" in text)         # False(大小は区別)
Python

基本構文と評価の流れ(ここが重要)

構文と返り値

「要素 in(または not in)コレクション」で書きます。結果は True/False の真偽値です。not in は in の結果を否定する形で評価され、書式はそのまま「要素 not in コレクション」で構いません。

nums = [1, 2, 3, 4, 5]
print(3 in nums)       # True
print(6 not in nums)   # True
Python

if 条件での自然な使い方

in / not in は比較演算子なので、if の条件にそのまま置けます。読みやすく、明確です。

users = {"hanako", "taro"}
name = "hanako"
if name in users:
    print("ログイン可")
else:
    print("未登録")
Python

データ型ごとの挙動(文字列・リスト/タプル・セット・辞書)

文字列:部分一致判定(大小は区別)

文字列に対する in は「部分文字列として含まれるか」を調べます。大小(大文字/小文字)は区別されます。

text = "Hello, world!"
print("o," in text)    # True
print("hello" in text) # False(case-sensitive)
Python

リスト/タプル:等価比較によるメンバーシップ

シーケンスに対する in は、左から順に等価比較して一致が見つかれば True を返します。要素型が混在する場合は、比較ルールに注意しましょう。

nums = [10, 20, 30]
print(20 in nums)      # True
print(99 in nums)      # False
Python

セット:高速な存在確認(ハッシュによる探索)

セットの in はハッシュを用いた高速検索が特徴です。大量要素の存在確認に向いています。

ids = set(range(100000))
print(12345 in ids)    # 高速に True
Python

辞書:対象は「キー」だけ(値は対象外)

dict に対する in は「キーの存在」を調べます。値の存在確認は d.values() を使う必要がありますが、値検索は線形走査になります。

user = {"name": "Hanako", "age": 20}
print("name" in user)          # True(キー)
print(20 in user)              # False(キーではない)
print(20 in user.values())     # True(値の中)
Python

性能と設計の勘所(重要ポイントを深掘り)

設計方針:高速化が必要ならセット/辞書を選ぶ

  • セット/辞書の in はハッシュ参照で高速。大量データの存在確認は、まずデータ構造をセット/辞書に寄せると効果的です。リスト/文字列は先頭からの線形探索なので、大きいほど遅くなります。

文字列判定は明確な仕様に

  • 文字列の in は部分一致・大小区別。要件次第で前処理(lower/casefold)や完全一致(==)へ切り替えると誤判定を防げます。

辞書は「キー」判定が基本

  • dict への in はキーのみ対象。値判定が必要なら values()/items() と組み合わせるのが安全です。

よくある落とし穴と安全策

文字列 in の意図しない部分一致

「’pro’ in ‘profile’」は True。完全一致が要件なら == を使うか、単語境界の正規表現で明示します。

print("pro" in "profile")   # True(部分一致)
print("pro" == "profile")   # False(完全一致)
Python

辞書の in を値判定に誤用

dict で「値の存在」を in で調べると誤り。キー判定と値判定を使い分けます。

d = {"A": 1, "B": 2}
print(1 in d)            # False(キーではない)
print(1 in d.values())   # True(値の中)
Python

大文字小文字の違いで見逃し

文字列判定は大小区別。事前に統一(lower/casefold)すると堅牢になります。

text = "Hello"
print("hello" in text.lower())  # True(前処理で統一)
Python

例題(定番から一歩先まで)

例題1:ブラックリスト判定(セットで高速化)

blacklist = {"spam@example.com", "bot@x"}
email = "spam@example.com"
if email in blacklist:
    print("拒否")  # 高速な存在確認
Python

例題2:辞書の必須キー検証

required = {"name", "age", "email"}
payload  = {"name": "Taro", "age": 25}

missing = required - payload.keys()
if missing:
    print("不足:", ", ".join(sorted(missing)))
Python

例題3:文字列の部分一致(ケース統一)

query = "tea"
text  = "Tea Latte"
if query.lower() in text.lower():
    print("ヒット")
Python

例題4:値でフィルタ(items と組み合わせ)

prices = {"coffee": 350, "tea": 280, "juice": 220}
expensive = {k: v for k, v in prices.items() if v >= 300}
print(expensive)  # {'coffee': 350}
Python

まとめ

in / not in は「含まれるか」を簡潔に判定する所属検査演算子です。文字列では部分一致、辞書ではキー判定、セット/辞書は高速、リスト/文字列は線形探索と挙動の違いを押さえると迷いません。要件に応じて前処理(casefold/lower)やデータ構造の選択(セット/辞書化)を行い、辞書の値判定は values()/items() を併用するのが安全な作法です。

タイトルとURLをコピーしました