当たり前の話ではありますが。
User
クラスの配列からuser_id
をキーに検索したい、email
をキーに検索したい等々の特定のキーがある場合、辞書型を経由すると非常に早く値を取得できます。
前提
- Python 3.9
対応
配列を辞書型に変換する
最初にUser
クラスを定義します。
class User: def __init__(self, user_id): self.user_id = user_id user_id: str
作成したUser
クラスを元にuser_id
をkeyとして、valueがUser
クラスの辞書型を作成します。
# ユーザ配列の作成 users = [User(user_id=str(x)) for x in range(100)] # user_idをkeyとし、valueを元のユーザとする user_dict: Dict[str, User] = {x.user_id: x for x in users}
検索する
後は辞書型の検索を行います。
user_dict.get('1')
後続の処理でNone
チェックをしたくない場合は、取得失敗した時のデフォルト値を入れてください。
user_dict.get('1', User(user_id='XXXX'))
配列のまま検索(ChatGPT3.5の回答)
ChatGPT3.5に回答を依頼すると、配列の処理中にif文を使用する方法が回答されました。Python 3エンジニア認定基礎試験でも、配列から目的の値だけを取得する方法はこちらだった記憶があります。
[x for x in users if x.user_id == '1']
処理速度の差
10万配列から100回検索をしました。サンプルコードは次のとおりです。
def test_01(): processingTime: float = 0 for y in range(10): start = time.perf_counter() a = [User(user_id=str(x)) for x in range(100000)] for x in range(100): [x for x in a if x.user_id == str(random.randrange(100000))] end = time.perf_counter() processingTime += end - start print(processingTime / 10)
# 処理時間(100回検索) # 配列のまま 7.498883651900087 # 辞書のまま 0.17779069980001622
参考程度に1回だけ実行した場合でも辞書型への変換コストを含めても辞書型で検索した方が早かったです。
# 処理時間(100回検索) # 配列のまま 0.2368281210000532 # 辞書のまま 0.19582450180000704
ソースコード
テストコードで動作確認しています。
終わりに
今までは配列から特定のキーを元に辞書型を作る方法を知らずに、愚直に処理していました。
Javaだと意識することが無かったのですが、本当はちゃんと変換した方が良かったんですかね。JITコンパイルで最適化されている気がしますが、裏付けはありません。
今後も、Pythonではきちんと計算速度を意識して処理していきたいです。