lambda関数
辞書のリストは、そのままでは並べ替えられない
sorted はリストを並べ替えた新しいリストを返す組み込み関数です。数値や文字列のリストなら、渡すだけで並びます。
Python
print(sorted([300, 120, 250]))[120, 250, 300] が出ます。ところが、おこづかい帳の記録は辞書のリストです。辞書どうしをどう比べればいいのか Python には分からないので、そのまま渡すと TypeError になります。
「金額を見て並べてほしい」という指示を、こちらから渡す必要があります。
何を見て並べるかを、関数で渡す
sorted には key というキーワード引数があります。ここに関数を渡すと、その関数が返した値を見て並べ替えてくれます。
Python
words = ["みかん", "パン", "たまご"]
print(sorted(words, key=len))文字数の少ない順に並びます。渡すのは 関数そのもの です。key=len(words) のようにかっこを付けて呼んでしまうと、返ってきた数値を関数として使おうとして TypeError になります。
len のような出来合いの関数で足りないときは、その場で小さな関数を書きます。それが lambda です。
Python
double = lambda x: x * 2
print(double(4))
print(sorted([12, 7, 20], key=lambda n: n % 10))8 と [20, 12, 7] が出ます。下は「10 で割った余り」の小さい順に並べたものです。lambda のうしろに引数、半角コロンのうしろに返す値を書きます。return は書きません。書いた式の値が、そのまま戻り値になります。引数には、sorted が 1 件ずつ渡してくれます。
lambdaは「その場かぎりの、名前を付けるほどでもない関数」を書く道具です。何行も書きたくなったら、素直にdefを使います。
sort は None を返す
sorted は新しいリストを返し、渡したリストはそのままです。前回の考え方どおり、元を壊さない関数は安心して使えます。
紛らわしいのが records.sort() のほうで、こちらは元のリストを並べ替えて None を返します。新しいリストが欲しいのに sort を使うと、戻り値が None になって落ちます。戻り値が None になっていたら、まずここを疑います。
lambda の中に return を書くと SyntaxError です。lambda は文ではなく式なので、返す値だけを書きます。
並べ替えの規則を関数として外から渡せる、という考え方は Python のあちこちで出てきます。並べ替えの基準が同じ値どうしは元の順番が保たれる点も、覚えておくと役に立ちます。
やってみよう
関数 sort_by_price(records) を実装してください。支出のリスト records を、金額 price の 小さい順 に並べ替えた新しいリストを return します。
sorted の key に lambda を渡し、1 件から金額を取り出して返すようにします。辞書からの取り出しは record["price"] の形です。
records が空のリストのときは空のリストが返ります。手元では並べ替えたあとに元の records を表示して、順番が変わっていないことも確かめてみてください。
要件
- 関数名は sort_by_price で、引数はリスト records の 1 つ
- 金額 price の小さい順に並べ替える
- sorted の key に lambda を渡して並べ替えの基準を指定する
- 元の records を書き換えず、新しいリストを返す
入出力例
sort_by_price([{"category":"娯楽","name":"映画","price":1800},{"category":"食費","name":"りんご","price":120},{"category":"交通費","name":"電車","price":320}]) → [{"category":"食費","name":"りんご","price":120},{"category":"交通費","name":"電車","price":320},{"category":"娯楽","name":"映画","price":1800}]
sort_by_price([{"category":"食費","name":"りんご","price":120},{"category":"食費","name":"パン","price":250}]) → [{"category":"食費","name":"りんご","price":120},{"category":"食費","name":"パン","price":250}]
sort_by_price([]) → []
sort_by_price([{"category":"日用品","name":"ノート","price":200},{"category":"日用品","name":"ペン","price":200},{"category":"その他","name":"おまけ","price":0}]) → [{"category":"その他","name":"おまけ","price":0},{"category":"日用品","name":"ノート","price":200},{"category":"日用品","name":"ペン","price":200}]
sort_by_price([{"category":"食費","name":"牛乳","price":180}]) → [{"category":"食費","name":"牛乳","price":180}]