0
1

More than 1 year has passed since last update.

【ソート】Python3の個人的つまずきポイント その4

Last updated at Posted at 2023-03-23

初めに

使用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 ]
]

image.png

ソート実行後リストの取得例

for e in result: # resultはソート後のリストを指す
    print(*e, sep=',')

Lv1 sorted関数を使おう

sorted()またはsort()を使う ことでお手軽に多重キーでのソートが可能です。

result = sorted(testsheet)
  • 1番目の要素、2番目の要素、3番目の要素・・・の順で優先的にソートします。
  • いずれも昇順でソートします。
  • 文字列はUnicodeコードに基づいてソートされます。
  • sorted(): 組み込み関数。「ソートした新たなリスト」を生成する
  • sort(): リスト型のメソッド。「元のリスト」をソートする

image.png

文字の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)

全ての要素に対し降順でソートできているのが分かります。
image.png

詳細は後述しますが下記でも同様のソート処理が可能です。

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の結果とは異なっています)
image.png

2人のMayさんの順番については公式ドキュメントにおいても言及されています。

ソートは、 安定 (stable) であることが保証されています。これはレコードの中に同じキーがある場合、元々の順序が維持されるということを意味します。

Lv4 昇順と降順を混ぜてみよう

Lv2の書式では「国語を昇順、数学を降順に並べたい」というときに対応できません。
そんなときは keyパラメータにてマイナスを適宜付けます

result = sorted(testsheet, key=lambda x:(x[1],-x[2]))

国語の点数が同点になったら数学の点数で降順に並べられていることがわかります。
image.png

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]))

贔屓された3名(4名)が表の上に来ていることがわかります。
image.png

贔屓ソートとは書きましたが、結局は数値を返すような関数を利用するためその数値をもとに昇順または降順でソートすることになります。

参考元

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1