sort メソッドで昇順・降順に並び替える

sort メソッドで昇順・降順に並び替える

list.sort()

 リスト型オブジェクトには、要素を昇順あるいは降順に並び替える sort()メソッド が備わっています。意外なことに、このメソッドをもつのは シーケンス の中でリスト型だけです。タプルや文字列を並び替えたいときは後述する sort() 関数を使います(もちろん、Python の構造をよく理解しているエンジニアにとっては、これは意外でももなんでもないでしょう。sort は明らかな破壊的メソッドであり、イミュータブルなシーケンスであるタプルや文字列にこのようなメソッドが備えられていないのは妥当なことです)。

list.sort(key, reverse)

 引数 reverse に False を指定するか省略すると 昇順、True を指定すると 降順 です。

# PYTHON_LIST_SORT

# In[1]

# リストを作成
num1 = [4, 2, 5, 1, 3]

# 昇順に並び替える
num1.sort()
print(num1)
[1, 2, 3, 4, 5]
# In[2]

# リストを作成
num2 = [4, 2, 5, 1, 3]

# 降順に並び替える
num2.sort(reverse = True)
print(num2)
[5, 4, 3, 2, 1]

 

key を指定して並べ替える

 今度は二種類のデータが一組となった要素をもつリストを考えてみましょう。例として、惑星の軌道長半径 (AU) と、質量 (1024kg) がペアになった一続きのデータを用意します。ちなみに軌道長半径とは惑星が楕円軌道を描くときの長いほうの半径、大まかにいえば太陽からの距離です。AU は地球の軌道長半径を 1 とした単位です。軌道長半径と質量はタプルの形式 [軌道長半径, 質量] でデータを作り、それぞれのタプルをリストの要素として並べます。初期状態では太陽から近いほうから「水・金・地・火・木・土」の順に並んでいます。これを質量の小さい順に並べることを考えてみます。

 sort()メソッドの第1引数 key には関数を指定します。このようなケースでは一般に lambda 式 とよばれる無名関数が使われます。lambda 式についての詳しい解説は別記事に譲りますが、ともかくこのように書けば、タプルの中の好きな要素をキーとして並べ替えることができることを知っておくと色々な場面で応用できます。

# PYTHON_SORT_KEY

# In[1]

# 水星,金星,地球,火星,木星,土星
# (軌道長半径[AU],質量[10**24kg])
planets = [(0.387,0.33),(0.723,4.87),(1,5.97),(1.524,0.942),(5.204,1898),(9.582,568)]

# タプルの2番目の要素(質量)を key に昇順に並び替えます
planets.sort(key = lambda tup: tup[1])

print(planets)
[(0.387, 0.33), (1.524, 0.942), (0.723, 4.87),
(1, 5.97), (9.582, 568), (5.204, 1898)]

 2 番目の要素を key にするので、インデックスは 1 であることに注意してください。
 lambda 式の変数はタプルであることがわかりやすいように tup としてありますが、この部分はどんな変数名でも構いません。要するに

planets.sort(key = lambda x: x[1])

のように記述すると、タプルの 2 番目の要素をキーに並び替えるということです。
 

itemgetter() を使って並び替える

 lambda 式を使うより、operator モジュールから itemgetter() を呼びだしたほうが、より簡潔なコードでソートを実装できます。

# PYTHON_SORT_ITEMGETTER

# In[1]

# itemgetter関数をインポート
from operator import itemgetter

# 水星,金星,地球,火星,木星,土星
# (軌道長半径[AU],質量[10**24kg])
planets = [(0.387,0.33),(0.723,4.87),(1,5.97),(1.524,0.942),(5.204,1898),(9.582,568)]

# 質量をキーにリストを並べ替える
planets.sort(key = itemgetter(1))

print(planets)
[(0.387, 0.33), (1.524, 0.942), (0.723, 4.87),
(1, 5.97), (9.582, 568), (5.204, 1898)]

 上のコードでは itemgetter() の引数でタプルのインデックスを指定しています。
 

見て試してわかる機械学習アルゴリズムの仕組み 機械学習図鑑

新品価格
¥2,894から
(2019/8/6 11:45時点)

いちばんやさしいPythonの教本 人気講師が教える基礎からサーバサイド開発まで 「いちばんやさしい教本」シリーズ

退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング

新品価格
¥3,996から
(2019/8/6 11:42時点)

sort() 関数

 sorted()関数 はリストのもつ sort()メソッドによく似た機能をもちますが、リストだけでなく、set やタプル、あるいは文字列なども引数に指定して並び替えることができます。

sorted(iterable, key=None,  reverse=False

 オプション引数 key は上で説明した sort()メソッドと同じように関数を指定しますが、昇順・降順に並び替えるだけなら省略して構いません。reverse に False を指定すると昇順、True を指定すると降順に並び替えます (デフォルトは False)。

文字列のソート

 sort()メソッドで文字列を昇順に並び替えてみましょう。アルファベットの昇順とは、a, b, c, d, e, ... という並び順のことです。

# PYTHON_ALPHABET_SORT

# In[1]

# 文字列を定義
my_str = "DACEB"

# アルファベットを昇順に並べたリストを作成
my_str = sorted(my_str)

print(my_str)
['A', 'B', 'C', 'D', 'E']

 sorted() 関数に引き渡したデータはすべて list 型となって戻ってきます。文字列で返してもらうには、join()メソッドでリストの要素を結合します。

# In[2]

# 文字列を定義
my_str = "DACEB"

# アルファベットを昇順に並べたリストを作成
my_str = sorted(my_str)

# リストの要素を再び結合
my_str = ''.join(my_str)

print(my_str)
ABCDE

 このような処理を頻繁に行うのであれば、次のような関数を作っておくと便利です。

# In[3]

# 文字列を昇順・降順に並び替える関数
def str_sort(x, s = False):
    y = sorted(x, reverse = s)
    return ''.join(y)

my_str = "DACEB"

# str_sort 関数を使って降順に並び替えます
my_str = str_sort(my_str, True)

print(my_str)
EDCBA

 str_sort 関数の引数 s は降順にするかどうかのオプション引数で、デフォルトでは False になっています。降順に並び替えたい場合は True を指定します。
 

タプルのソート

 sorted() の引数にタプルを指定しても、やはりリスト型で戻ってきます。

# PYTHON_TUPLE_SORT

# In[1]

# タプルを定義
num_tup = (1, 2, 3, 4, 5)

# タプルの要素を降順に並べ替えたリストを作成
num_list = sorted(num_tup, reverse = True)

print(num_list)
[5, 4, 3, 2, 1]

 タプルを渡して並び替えたうえで、やはりタプルで返してもらうならば、先ほどの文字列の場合と同様にタプル専用の並び替え関数を作っておきます。

# In[2]

# タプルを昇順・降順に並び替える関数
def tup_sort(x, s = False):
    y = sorted(x, reverse = s)
    return tuple(y)

# タプルを定義
num_tup = (1, 2, 3, 4, 5)

# 関数を使ってタプルを降順に並び替えます
num_tup = tup_sort(num_tup, True)

print(num_tup)
(5, 4, 3, 2, 1)

 

list.reverse()

 list.reverse() はリストの要素を逆順に並び替えるメソッドです。

# PYTHON_LIST_REVERSE

# In[1]

# リストを定義
framework = ["Django", "Flask", "Plone", "Bottle"]

# リストの並び順を反転させる
framework.reverse()

print(framework)
['Bottle', 'Plone', 'Flask', 'Django']