リスト内包表記
「入れ物を作る、回す、入れる」を毎回書いている
条件に合うものだけを取り出す処理は、これまでの書き方だと必ず 4 行になります。
Python
result = []
for record in records:
if record["price"] >= 1000:
result.append(record)やっているのは「入れ物を作る」「回す」「合えば入れる」の 3 つで、条件のところ以外は毎回まったく同じです。この決まりきった形を 1 行に畳める記法が リスト内包表記 です。
Python
result = [record for record in records if record["price"] >= 1000]角かっこの中に for があるのが目印で、上の 4 行と同じ結果になります。短く書けるから偉いのではありません。角かっこを見た瞬間に「新しいリストを作っている」と伝わるところに価値があります。
左に何を書くかで、返るものが変わる
内包表記は 3 つの部品でできています。
Python
[ 式 for 変数 in もとのリスト if 条件 ]読む順番は書いてある順とは違います。まず for で何を回すかをつかみ、次に if で絞り込み、最後にいちばん左の 式 で「何を入れるか」を決めます。
この左の式が自由なところが要です。変数をそのまま書けば要素がそのまま入り、r["price"] のように書けば金額だけのリストになります。
Python
names = [r["name"] for r in records]
prices = [r["price"] for r in records if r["price"] >= 1000]1 つ目は全件の品名、2 つ目は 1000 円以上の金額です。if は書かなくても構いません。
元のリストは変わりません。内包表記も、スライスや sorted と同じ「新しく作って返す」仲間です。
if を左に書くと、別の意味になる
つまずきやすいのが if の位置です。絞り込みの if は for の うしろ に書きます。
Python
[r["name"] if r["price"] >= 1000 else "-" for r in records]こちらは第 3 章の三項演算子で、件数は減りません。条件に合わないものを捨てるのではなく、入れる値を切り替えているだけです。件数が変わってほしいのに変わらないときは、if の位置を疑います。
もう 1 つ、内包表記の中に append は書きません。[result.append(r) for r in records] と書くと、append の戻り値である None が並んだリストができます。入れる仕事は角かっこがやってくれます。
やってみよう
関数 only_food(records) を実装してください。支出の辞書が並んだリストから、category が "食費" のものだけを集めた新しいリストを return します。
リスト内包表記で 1 行で書いてください。取り出すのは金額や品名ではなく 辞書そのもの です。元の並び順は変えず、条件に合うものが 1 件も無いときや空リストのときは空リスト [] を返します。
要件
- 関数名は only_food で、引数は records の1つ
- リスト内包表記を使って新しいリストを作る
- category が "食費" の辞書だけを、辞書のまま取り出す
- 元の並び順を保ち、該当が無いときは空リストを返す
入出力例
only_food([{"category":"食費","name":"りんご","price":120},{"category":"日用品","name":"ノート","price":200},{"category":"食費","name":"牛乳","price":180}]) → [{"category":"食費","name":"りんご","price":120},{"category":"食費","name":"牛乳","price":180}]
only_food([{"category":"娯楽","name":"映画","price":1800},{"category":"交通費","name":"電車代","price":320}]) → []
only_food([]) → []
only_food([{"category":"食費","name":"りんご","price":120},{"category":"食費","name":"牛乳","price":180}]) → [{"category":"食費","name":"りんご","price":120},{"category":"食費","name":"牛乳","price":180}]
only_food([{"category":"食費","name":"試供品","price":0},{"category":"日用品","name":"ペン","price":150}]) → [{"category":"食費","name":"試供品","price":0}]