初めに
- 不定期に備忘録を投稿します。
使用Version:Python 3.11.2
公式ドキュメントにも同様の内容が記載されています。
https://docs.python.org/ja/3/howto/sorting.html
多次元リストのソート
今回は下記表を例にとって説明します。
testsheet = [
['Matt', 23, 80 ],
['Zill', 55, 46 ],
['May', 70, 90 ],
['May', 70, 80 ],
['Tyler', 55, 70 ],
['Tomothy',55, 70 ],
['太郎', 55, 70 ],
['はるか', 40, 70 ],
['$imon', 40, 70 ],
['ωatson', 40, 70 ],
['Tomothy',43, 80 ]
]
ソート実行後リストの取得例
for e in result: # resultはソート後のリストを指す
print(*e, sep=',')
Lv1 sorted関数を使おう
sorted()
またはsort()
を使う ことでお手軽に多重キーでのソートが可能です。
result = sorted(testsheet)
- 1番目の要素、2番目の要素、3番目の要素・・・の順で優先的にソートします。
- いずれも昇順でソートします。
- 文字列はUnicodeコードに基づいてソートされます。
-
sorted()
: 組み込み関数。「ソートした新たなリスト」を生成する -
sort()
: リスト型のメソッド。「元のリスト」をソートする
文字のUnicodeコードはord関数を用いることでも調べられます。
for e in result:
print('0x%04X'%(ord(e[0][0])))
詳細は後述しますが下記でも同様のソート処理が可能です。
result = sorted(testsheet, key=lambda x:(x[0],x[1],x[2]), reverse=False)
Lv2 降順でソートしよう
reverseパラメータを指定する ことで昇順または降順の指定が可能です。
# 全要素を降順でソートする
result = sorted(testsheet, reverse=True)
詳細は後述しますが下記でも同様のソート処理が可能です。
result = sorted(testsheet, key=lambda x:(x[0],x[1],x[2]), reverse=True)
result = sorted(testsheet, key=lambda x:(-x[0],-x[1],-x[2]))
Lv3 ソートキーを絞ろう
key
パラメータに関数を指定する ことでソートキーを定義できます。
ここでは「"名前"、"国語"をキーに昇順ソートする」「"数学"をキーにはしない」ことをラムダ式で明記します。
result = sorted(testsheet, key=lambda x:(x[0],x[1]))
表には2人のMayさんがいますが、数学については昇順でソートされていないことが分かります。
(Lv1の結果とは異なっています)
2人のMayさんの順番については公式ドキュメントにおいても言及されています。
ソートは、 安定 (stable) であることが保証されています。これはレコードの中に同じキーがある場合、元々の順序が維持されるということを意味します。
Lv4 昇順と降順を混ぜてみよう
Lv2の書式では「国語を昇順、数学を降順に並べたい」というときに対応できません。
そんなときは key
パラメータにてマイナスを適宜付けます。
result = sorted(testsheet, key=lambda x:(x[1],-x[2]))
国語の点数が同点になったら数学の点数で降順に並べられていることがわかります。
Lv5 贔屓しよう
今まで昇順または降順でソートしましたが「お気に入りの子を優先して上に出す」ことも可能です。
key
パラメータに別途関数を指定する ことで「贔屓ソート、数学で降順ソート、名前で昇順ソート」のような処理を実現できます。
# 贔屓生徒リスト
favsheet = ["はるか","May","Zill"]
# 贔屓レベルを出力する関数。値が低いほど贔屓度が高いものとする
#(はるか(0) > May(1) > Zill(2) > その他大勢(3) の順に贔屓する)
def get_fav_index(x):
for i, name in enumerate(favsheet):
if name == x[0]:
return i
return len(favsheet)
'''
別の書き方
get_fav_index = lambda x:\
[i if name == x[0] else len(favsheet) for i, name in enumerate(favsheet)]
'''
# 贔屓ソート、数学で降順ソート、名前で昇順ソート
result = sorted(testsheet, key=lambda x:(get_fav_index(x),-x[2],x[0]))
贔屓ソートとは書きましたが、結局は数値を返すような関数を利用するためその数値をもとに昇順または降順でソートすることになります。