sortedとkeyの応用
このレッスンでできるようになること。sorted の key にタプルを返す関数を渡して、複数の条件を組み合わせた並べ替えができるようになります。
sorted(リスト, key=関数) は、要素そのものではなく「関数に通した結果」を基準に並べ替えます。並べ替え用の値を取り出す関数を渡す、という意味で sorted も高階関数です。
Python
numbers = [-8, 3, -1]
by_size = sorted(numbers, key=abs)
print(by_size) # [-1, 3, -8]条件を2つ以上重ねたいときは、key でタプルを返します。タプルは前の要素から順に比べられるので、(カテゴリ, 金額) を返せばカテゴリ順に並び、同じカテゴリの中では金額順に並びます。降順にしたい数値はマイナスを付けると、昇順のまま逆順を表せます。
配送の優先度と箱の重さで考えます。優先度は小さい順、同じ優先度なら重い順にします。
Python
parcels = [(2, 3), (1, 2), (1, 5)]
parcel_key = lambda parcel: (parcel[0], -parcel[1])
print(sorted(parcels, key=parcel_key)) # [(1, 5), (1, 2), (2, 3)]同じ優先度の箱では、重さ5のキーは -5、重さ2のキーは -2 です。-5 が先に並ぶので重い箱からになります。key に渡す関数は、要素を1つ受け取って比較用のタプルを返します。
ここで気を付けたいのが、キーが完全に同じ要素が複数あるときです。Python の sorted は安定ソートなので元の順序を保ちますが、元データの並びが変われば結果も変わり、外から見ると「並びが安定しない」ように見えます。そこで、最後に品名のような重複しない値をキーへ足しておきます。(カテゴリ, -金額, 品名) まで指定すれば順序は一意に決まり、いつ何度実行しても同じ結果になります。
なお sorted は新しいリストを返し、元のリストは変えません。元のデータを残したまま別の並びが欲しいときに使う道具だと覚えてください。
演習では比較用タプルを返す lambda と sorted を自分で書きます。並べ替えた支出から品名だけを取り出す _names(ordered) は準備済みです。カテゴリ、金額、品名の順に比較の優先順位を決めてください。
要件
- カテゴリ、符号を反転した金額、品名を並べたタプルを返す lambda を作る
- その関数を key に指定し、sorted を1回使う
- 並べ替えた支出を _names に渡して返す