はじめに
以前phpでarray_reduce()を使ってネストのある配列の値を検索する処理を調べる機会があり、他の言語、例えばpythonを使用するとどのように書けるのか気になったので、調べてみました。
すると、pythonではfor文の代わりにリスト内包表記というものを使うと、よりシンプルに書けるということがわかりました。
今回はそんなリスト内包表記について、for文で記述した場合と比較しつつ備忘録としてまとめていきたいと思います。
やりたいこと
ネストのある元配列を一意の値で検索して、同じの要素の中で深さの違うキーの値を取り出したいと思います。
文章だけだとわかりにくいですね。
以下のようにネストされた配列があるとします。
arrays = [
{
"id": 930,
"mail": "suga59@ex.com",
"sendMailFlg": "1",
"user": {
"id": 02,
"name": "菅原道真",
"era": "平安時代",
"event": "清涼殿落雷事件"
}
},
{
"id": 935,
"mail": "masakado-taira@ex.com",
"sendMailFlg": "1",
"user": {
"id": 01,
"name": "平将門",
"era": "平安時代",
"event": "平将門の乱"
}
},
{
"id": 1156,
"mail": "sutoku-4767@ex.com",
"sendMailFlg": "0",
"user": {
"id": 03,
"name": "崇徳天皇",
"era": "平安時代",
"event": "保元の乱"
}
}
]
この時「user
キーの中にあるid
の値で検索し、該当する要素のmail
の値を配列で取得する」という処理がしたいとしま
す。
イメージはできたでしょうか?
まずはこの処理を、for文を使用して作成してみましょう。
実装
for文を使用した例
userId = 02 # 検索したい値
mailList = []
for array in arrays:
if array.get("user")["userId"] == userId:
mailList.append(array.get("mail"))
print(mailList)
# ['suga59@ex.com']
空の配列を用意して、for文で各要素のuser
キーの値の中のid
と検索値が一致するかを判定。trueであれば用意した配列の中にその要素のmail
キーの値を追加する、という内容ですね。
pythonで記述する場合、リストから新たなリストを生成する際に使用する「リスト内包表記」を用いることで、上記の処理を下のように1行で表すことができます。
リスト内包表記を使用した例
userId = 02 # 検索したい値
mailList = [array.get("mail") for array in arrays if array.get("user")["userId"] == userId]
print(mailList)
# ['suga59@ex.com']
for文と比べて、シンプルな記述になったのがわかりますね。
次では、リスト内包表記の基本的な内容についてまとめていきたいと思います。
リスト内包表記とは
基本型は以下の通りです。
[式 for 任意の変数名 in イテラブルオブジェクト]
実装例で考えると「配列の各要素のmail
の値をmailList
に追加する」までの処理がこれにあたります。
mailList = [array.get("mail") for array in arrays]
print(mailList)
# ['suga59@ex.com', 'masakado-taira@ex.com', 'sutoku-4767@ex.com']
実装例ではこれにif文を追加しているので、型としては
[式 for 任意の変数名 in イテラブルオブジェクト if 条件式]
となります。
ちなみに型の「式」の箇所には三項演算子を用いることも可能なので、「user
キーの値の中にあるid
の値が検索値と一致する要素であればmail
の値をmailList
に追加し、そうでなければ空文字を追加する」なんて処理も1行で表すことができます。
# 型
[真のときの値 if 条件式 else 偽のときの値 for 任意の変数名 in イテラブルオブジェクト]
userId = 02 # 検索したい値
mailList = [array.get("mail") if array.get("user")["id"] == userId else "" for array in arrays]
print(mailList)
# ['suga59@ex.com', '', '']
部分一致で検索
完全一致による検索だけでなく、部分一致での検索も可能です。
せっかくなので「user
キーの値の中にあるevent
の値に「乱」が含まれている要素のmail
の値をmailList
に追加する」処理で確認してみましょう。
# 型
[式 for 任意の変数名 in イテラブルオブジェクト if 検索したい文字列 in 検索対象となる文字列]
mailList = [array.get("mail") for array in arrays if "乱" in array.get("user")["event"]]
print(mailList)
# ['masakado-taira@ex.com', 'sutoku-4767@ex.com']
検索したい文字列 not in 検索対象となる文字列
にすることで、検索したい文字列が含まれていない要素を取得することも可能です。
# 型
[式 for 任意の変数名 in イテラブルオブジェクト if 検索したい文字列 not in 検索対象となる文字列]
mailList = [array.get("mail") for array in arrays if "乱" not in array.get("user")["event"]]
print(mailList)
# ['suga59@ex.com']
おわりに
いかがでしたでしょうか?
リスト内包表記というものを初めて知り、またphpでは見ない表記なので、今回記事にするにあたり調べていて面白かったです。
今回はリスト内包表記を用いた値の検索について取り上げましたが、正規表現や複数条件、値からキーを検索することも可能とのことです。
興味のある方はぜひ調べてみてください。
最後まで閲覧いただきありがとうございます。
参考: