LoginSignup
1
2

More than 1 year has passed since last update.

【Python】多次元配列での昇順・降順が混ざった際のソートのやり方について

Posted at

初めまして、大学院生をしているhinoと申します。

今回はAtCoderの過去問を解いていて、多次元配列の昇順と降順が混ざったソートの方法が知りたくなり、まとめました。

解いていた問題

問題概要

市名とレストランの点数が与えられ、次のような順でレストランを紹介します。

  • 市名は辞書順で早い方から紹介
  • 同じ市に複数のレストランがある際には点数の高い方から紹介

この問題は市名を昇順ソートし、点数を降順ソートすることで目的の並び方にすることができるのですが、多次元配列の昇順と降順が混在するソートになってしまうためその実装について考えてみました。

例として問題のテストケース1を考えてみます。

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

同時に昇順・降順ソートは指定できないので、別々に行ってみます。

#市名について昇順ソート
data = sorted(data, key=lambda x: x[0])

#点数について降順ソート
data = sorted(data, key=lambda x: x[1], reverse=True)
print(data)

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

このように順序が乱れるためうまくいきません。
そこで調べてみたところ、Pythonのリファレンスに次のような記述がありました。

ソートの安定性と複合的なソート
ソートは、 安定 (stable) であることが保証されています。これはレコードの中に同じキーがある場合、元々の順序が維持されるということを意味します.......
この素晴しい性質によって複数のソートを段階的に組み合わせることができます。例えば、学生データを grade の降順にソートし、さらに age の昇順にソートしたい場合 には、まず age でソートし、次に grade でもう一度ソートします:

どうも、降順を優先すると良さそうとのことですので試してみましょう。

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

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

目的通りのソートができました!!

...ただ、1行で書きたいなと思うんですよね...。
そこで思いついたのが 正数を降順ソートにしたいなら負数を昇順ソートすればよいということです。

data = sorted(data, key=lambda x: (x[0], -x[1]))
print(data) 

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

この方法でも無事に目的のソートができました。多分ですが、こちらの方がマイナスを取るだけという簡単な方法かつ1行で書けるので、バグらせにくいのかなと思います。

1
2
2

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
1
2