静かなる名辞

pythonとプログラミングのこと

【python】多重リストを昇降混ぜてソート

 pythonでは多重リストのソートは次のように書ける。

import random
from pprint import pprint

data = [[random.randint(0, 20), 
         random.randint(0, 20)]
        for _ in range(10)]

print("data")
pprint(data)

print("\nsorted data")
pprint(sorted(data, key=lambda x:(x[0], x[1])))

 結果

data
[[6, 10],
 [11, 4],
 [3, 1],
 [17, 10],
 [8, 5],
 [3, 15],
 [13, 9],
 [8, 12],
 [11, 12],
 [20, 5]]

sorted data
[[3, 1],
 [3, 15],
 [6, 10],
 [8, 5],
 [8, 12],
 [11, 4],
 [11, 12],
 [13, 9],
 [17, 10],
 [20, 5]]

 参考:
【Python】ソート

 要するにkeyをこのような形式にして、各子リストの要素を桁のようにみなしてソートできる訳だ(いまいちうまく表現できないけど)。

 降順にしたければ、reversed=Trueを指定するだけ。

import random
from pprint import pprint

data = [[random.randint(0, 20), 
         random.randint(0, 20)]
        for _ in range(10)]

print("data")
pprint(data)

print("\nsorted data")
pprint(sorted(data, key=lambda x:(x[0], x[1]), reverse=True))

 結果

data
[[4, 19],
 [3, 8],
 [15, 9],
 [13, 9],
 [7, 10],
 [8, 12],
 [20, 2],
 [19, 17],
 [7, 11],
 [5, 11]]

sorted data
[[20, 2],
 [19, 17],
 [15, 9],
 [13, 9],
 [8, 12],
 [7, 11],
 [7, 10],
 [5, 11],
 [4, 19],
 [3, 8]]


 では、最初の要素は昇順、次の要素は降順にしたいときは、どうしたら良いのでしょう。

 reverse引数はbooleanのみ受け付ける。tupleが渡せたら良かったのだけど、渡せないので仕方ない。

 しかし、そんなに心配する必要はない。

ソート HOW TO — Python 3.6.5 ドキュメント

 によると、pythonのソートは安定ソートである。このことを利用して、こう書ける。

import random
from pprint import pprint

data = [[random.randint(0, 20), 
         random.randint(0, 20)]
        for _ in range(10)]

print("data")
pprint(data)

print("\nsorted data")
tmp = sorted(data, key=lambda x:x[1], reverse=True)
pprint(sorted(tmp, key=lambda x:x[0]))

 結果

data
[[0, 12],
 [13, 1],
 [15, 6],
 [14, 4],
 [11, 1],
 [7, 2],
 [17, 3],
 [13, 8],
 [0, 19],
 [19, 6]]

sorted data
[[0, 19],
 [0, 12],
 [7, 2],
 [11, 1],
 [13, 8],
 [13, 1],
 [14, 4],
 [15, 6],
 [17, 3],
 [19, 6]]
[0, 19],
 [0, 12],

 とか
>||
[13, 8],
[13, 1],
|