つくる 抽出・変換パイプライン

このレッスンでできるようになること。この章で学んだ高階関数だけを組み合わせて、抽出から変換、並べ替え、集計までを一本の流れとして書けるようになります。新しい文法は出てきません。

家計簿の集計は、たいてい同じ形をしています。まず必要な支出を絞り込み、次に扱いやすい形へ直し、最後に1つの答えへまとめる。この3段階を、それぞれ filter と map と reduce が担当します。段ごとに役割がはっきりしているので、後から条件を1つ足したいときも触る場所が1か所で済みます。

picked = list(filter(lambda e: e["category"] == "食費", expenses)) taxed = list(map(lambda e: {"name": e["name"], "amount": e["amount"] * 110 // 100}, picked))

書くときの約束を3つ確認しておきます。1つめは、map と filter の結果を必ず list() に通すことです。中間の変数に map オブジェクトのまま入れておくと、2回目に使ったときには空になっていて、合計が 0 になるといった原因の分かりにくい不具合になります。

2つめは、金額を int のまま持ち回ることです。税込計算に * 1.1 を使うと端数が float に化け、合計や比較の結果が環境によってぶれます。* 110 // 100 で int を保ちます。

3つめは、並べ替えの key に重複しない値まで含めることです。同じ金額の支出が並ぶと順序が読み手には決まって見えないので、金額の次に品名を足して一意にします。

仕上げに any で予算の見張りを足せば、抽出から判定までが高階関数だけでつながります。

要件

  1. 抽出は filter、変換は map、合計は reduce を使う
  2. map と filter の結果は list に通してから次で使う
  3. 税込金額は amount * 110 // 100 で計算し int のまま扱う
  4. 並べ替えは金額降順、同額なら品名昇順にする
  5. 対象カテゴリが1件も無いときは names が空リスト、total は 0 になる

入出力例

summarize([{"amount":220,"category":"食費","name":"牛乳"},{"amount":1280,"category":"食費","name":"コーヒー豆"},{"amount":1280,"category":"食費","name":"紅茶"},{"amount":640,"category":"交通費","name":"電車代"}], "食費", 3000){"has_expensive":true,"names":["コーヒー豆","紅茶","牛乳"],"over_budget":true,"total":3058} summarize([{"amount":220,"category":"食費","name":"牛乳"},{"amount":640,"category":"交通費","name":"電車代"}], "交通費", 3000){"has_expensive":false,"names":["電車代"],"over_budget":false,"total":704} summarize([{"amount":220,"category":"食費","name":"牛乳"},{"amount":640,"category":"交通費","name":"電車代"}], "日用品", 1000){"has_expensive":false,"names":[],"over_budget":false,"total":0}

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.py
学習モード

メモ

つくる 抽出・変換パイプライン

⌘S で保存