2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

多次元リストを複数行でソートしたいとき

Posted at

1次元の時

import random
a = [random.randint(-5, 5) for _ in range(10)]
a.sort()
print('sorted: {}'.format(a))

>>      [4, -3, 0, -2, 1, 4, -1, -3, 2, 3]
sorted: [-3, -3, -2, -1, 0, 1, 2, 3, 4, 4]

予想通り、小さい順に並びます。
文字列についても同様に、

# 適当にstr型のリストを作る
s = [chr(random.randint(97, 97+25)) for i in range(10)]
print(s)
s.sort()
print('sorted: {}'.format(s))
>>      ['v', 'm', 'h', 'n', 'o', 'i', 'w', 'o', 'q', 'r']
sorted: ['h', 'i', 'm', 'n', 'o', 'o', 'q', 'r', 'v', 'w']

#多次元のとき
例としてこのようなリストを考えます。(※ABC128-Bのテストケースより)

a = [['khabarovsk', 20],
     ['moscow', 10],
     ['kazan', 50],
     ['kazan', 35],
     ['moscow', 60],
     ['khabarovsk', 40]]

この配列の1行目を並び替え、1行目の要素が同じ物は2行目の数字が小さい順に並び替えたいとします。

方法1: sortedの引数keyをいじる

下記のようにkeyを指定することで、指定した行が順番にソートされます。

print(sorted(a, key=lambda x:(x[0], x[1])))
>>
[['kazan', 35], 
 ['kazan', 50], 
 ['khabarovsk', 20], 
 ['khabarovsk', 40], 
 ['moscow', 10], 
 ['moscow', 60]]

# 逆の順番で指定すると
print(sorted(a, key=lambda x:(x[1], x[0])))
>>
[['moscow', 10],
 ['khabarovsk', 20],
 ['kazan', 35],
 ['khabarovsk', 40],
 ['kazan', 50],
 ['moscow', 60]]

# 数値の場合は - をつけることで大きい順にソートすることができます。
print(sorted(a, key=lambda x:(x[0], -x[1])))
>>
[['kazan', 50],
 ['kazan', 35],
 ['khabarovsk', 40],
 ['khabarovsk', 20],
 ['moscow', 60],
 ['moscow', 10]]

##方法2: ただのsort()で事足りることも
まず多次元リストに対して、sort()を使ってみると、

b = [[chr(random.randint(97, 97+25)), random.randint(-5, 5)] for i in range(5)]
print(b)
b.sort
print('sorted: {}'.format(b))
>>
        [['r', 1], ['a', 0], ['k', -2], ['z', -2], ['g', -3]]
sorted: [['a', 0], ['g', -3], ['k', -2], ['r', 1], ['z', -2]]

このように、基本は第1行のみに沿ってソートされます。

ここで、例のような場合にsort()を使ってみます。

a.sort()
print(a)
>>
[['kazan', 35],
 ['kazan', 50],
 ['khabarovsk', 20],
 ['khabarovsk', 40],
 ['moscow', 10],
 ['moscow', 60]]

あれ??
方法1のkeyを順に指定した時と同じ結果が得られました。
pythonのsort関数は基本第一行でソートされますが、第一行の要素が同じ列に対しては次の第二行を比較してソートされるみたいです。
なので例のようなことをしたい場合は単にsort()を使うだけでよかったのです。

工夫すると数値が大きい順にもできます。

for i in a:
  i[1] = -i[1]
a.sort()
print(a)
>>
[['kazan', -50],
 ['kazan', -35],
 ['khabarovsk', -40],
 ['khabarovsk', -20],
 ['moscow', -60],
 ['moscow', -10]]

まとめ

  • ソート
    • sorted(a, key=lambda x:(x[i], x[j], x[k], ...)
    • sort()基本第一行でソートされるが、第一行の要素が同じ列に対しては次の第二行を比較してソートされる
2
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?