【Python入門】listのソート(sort, sorted)

リストの要素をソートする方法として、 sort()sorted()のどちらが一般的に用いられる。 それぞれのメソッドの特徴や性能をまとめる。

概要

sort()sorted()の比較

sort()sorted()の性能を比較すると、下記のようになる。

基本的には、sort()が破壊的なメソッドである点ソートできる対象の豊富さ を考慮すると、sorted()を使う方が良いと思われる。 しかし、元のリストが不要であれば、 sort()の方がメモリ効率が良い。

項目 sort() sorted()
効果 元のリストをソート(破壊的 ※1) ソートした新たなリストを生成
(非破壊的)
ソートできる対象 リストのみ イテラブルなオブジェクト
(リスト、タプル、辞書など)
戻り値の型 NoneType list
メモリ消費 わずかに効率的 ※2 わずかに非効率的

※1:破壊的メソッドとは、引数、あるいは呼び出し先のオブジェクトを変化させるメソッド。 一般的に、破壊的メソッドは、あまり使うべきではない、とされている。

※2:sorted() は、ソートした新たなリストを生成するので、sort()と比較すると、わずかにメモリ効率が悪いです。

簡単的な使い方紹介

sort()sorted()の使い方を簡単に紹介する。 詳しくは、下記の「sort()sorted()の詳細」を参照。

まず、sort()の使い方を紹介する。

#sort()の使い方
#数値(昇順)
>>>list_a = [5,3,8]
>>>list_a.sort()
>>>list_a
[3, 5, 8]

#数値(降順)
>>>list_b = [5,3,8]
>>>list_b.sort(reverse=True)
>>>list_b
[8, 5, 3]

次に、sorted()の使い方を紹介する。

#sorted()の使い方
#数値(昇順)
>>>list_c = [5,3,8]
>>>sorted(list_c)
[3, 5, 8]

#数値(降順)
>>>list_d = [5,3,8]
>>>sorted(list_d, reverse=True)
[8, 5, 3]

sort()sorted()の詳細

sort()

sort()は、リストの組み込みメソッドで、 呼び出し先のリストを破壊的にソートする。

使い方

デフォルトでは、リストの要素が数値であれば数値が昇順に、 リストの要素が文字列であれば文字コードの並び方になる。 逆順に並べたい場合は、引数reverseTrueとする。

#数値(昇順)
>>>list_a = [5,3,8]
>>>list_a.sort()
>>>list_a
[3, 5, 8]

#文字列
>>>list_b = ['c','b','aaa']
>>>list_b.sort()
>>>list_b
['aaa', 'b', 'c']

#数値(降順)
>>>list_c = [5,3,8]
>>>list_c.sort(reverse=True)
>>>list_c
[8, 5, 3]

次に、リストの要素がタプルの場合を考える。 (タイトル、ランキング、売上)で構成されたタプルのリストを用意する。 このランキングは、海外のサイト1に掲載されていたFinal Fantasyの人気ランキングであり、 売上は、それぞれのFinal Fantasyのタイトルの売上2。(M=Million)

ちなみに、個人的にはff10が一位、ff7が二位、ff8が三位という感じです。 トップ3入りしていなくて寂しいです。。。

>>>list_a = [
...    ('ff07',6,'3.28M'),
...    ('ff10',9,'2.50M'),
...    ('ff08',11,'3.69M')] #title, ranking, sales 

tuple_aに対してそのままsort()を使用すると、 タプルの 0番目の要素であるタイトルの昇順にソートされる。

#そのまま
>>>list_a.sort() 
[('ff07', 6, '3.28M'), ('ff08', 11, '3.69M'), ('ff10', 9, '2.50M')]

タプルの0番目以外の要素でソートしたい場合、 Key関数と無名関数lamdaを用いてソートすることができる。

#0番目の要素(タイトル)でソート
>>>list_a.sort(key=lambda x: x[0]) 
>>>list_a
[('ff07', 6, '3.28M'), ('ff08', 11, '3.69M'), ('ff10', 9, '2.50M')]

#1番目の要素(ランキング)でソート
>>>list_a.sort(key=lambda x: x[1]) 
>>>list_a
[('ff07', 6, '3.28M'), ('ff10', 9, '2.50M'), ('ff08', 11, '3.69M')]

#2番目の要素(売上)でソート
>>>list_a.sort(key=lambda x: x[2]) 
>>>list_a
[('ff10', 9, '2.50M'), ('ff07', 6, '3.28M'), ('ff08', 11, '3.69M')]
注意点

sort()は、元のリスト自体を書き換える破壊的処理を行うので、 戻り値はNoneとなる。

#数値(昇順)
>>>list_a = [5,3,8]
>>>list_b = list_a.sort()
>>>list_a #元リスト
[3, 5, 8]

>>>list_b #None
>>>print(list_b)
None
>>>type(list_b)
NoneType

sorted()

sorted()は、リスト以外にもイテラブルなオブジェクトから ソートしたリストを作成する組み込み関数である。

使い方(リスト)

sort()と同様に、デフォルトでは リストの要素が数値であれば数値が昇順に、 リストの要素が文字列であれば文字コードの並び方になる。 逆順に並べたい場合は、引数reverseTrueとする。

#数値(昇順)
>>>list_a = [5,3,8]
>>>sorted(list_a)
[3, 5, 8]

#文字列
>>>list_b = ['c','b','aaa']
>>>sorted(list_b)
['aaa', 'b', 'c']

#数値(降順)
>>>list_c = [5,3,8]
>>>sorted(list_c, reverse=True)
[8, 5, 3]

リストの要素がタプルの場合も、 sort()と同様にソートすることができる。

>>>list_a = [
...    ('ff07',6,'3.28M'),
...    ('ff10',9,'2.50M'),
...    ('ff08',11,'3.69M')] #title, ranking, sales 

#そのまま
>>>sorted(list_a) 
[('ff07', 6, '3.28M'), ('ff08', 11, '3.69M'), ('ff10', 9, '2.50M')]


#0番目の要素(タイトル)でソート
>>>sorted(list_a, key=lambda x: x[0]) 
[('ff07', 6, '3.28M'), ('ff08', 11, '3.69M'), ('ff10', 9, '2.50M')]

#1番目の要素(ランキング)でソート
>>>sorted(list_a, key=lambda x: x[1]) 
[('ff07', 6, '3.28M'), ('ff10', 9, '2.50M'), ('ff08', 11, '3.69M')]

#2番目の要素(売上)でソート
>>>sorted(list_a, key=lambda x: x[2])
[('ff10', 9, '2.50M'), ('ff07', 6, '3.28M'), ('ff08', 11, '3.69M')]
使い方(辞書)

次に、リスト以外のイテラブルなオブジェクトである 辞書をソートする場合を考える。

本来、辞書には順序がないが、sortedを使うことで、keyの昇順に並べることができる。 注意すべき点として、以下の二点。

① ソート後はリストになる。

 sortedの戻り値はリストなので、 元々の引数が辞書だったとしても、ソート後はリストになる。

②辞書のkeyvalueの関係を保存するには、items()を使う必要がある。

 辞書をそのままsorted()の引数として使うと、keyだけのリストになってしまう。

>>>dict_a = {'ff07':6,'ff10':9,'ff08':11}
>>>list_a = sorted(dict_a.items())
>>>list_a
[('ff07', 6), ('ff08', 11), ('ff10', 9)]

#注意①
>>>type(list_a) 
list

#注意②
>>>list_b = sorted(dict_a)
>>>list_b
['ff07', 'ff08', 'ff10']

デフォルトではkeyの昇順に並べるが、 Key関数と無名関数lamdaを用いることで、 valueの昇順に並べることができる。

>>>dict_a = {'ff07':6,'ff10':9,'ff08':11}

#指定なし(keyの昇順)
>>>list_a = sorted(dict_a.items())
>>>list_a
[('ff07', 6), ('ff08', 11), ('ff10', 9)]

#0番目の要素(key)でソート(keyの昇順)
>>>list_b = sorted(dict_a.items(), key=lambda x: x[0])
>>>list_b
[('ff07', 6), ('ff08', 11), ('ff10', 9)]

#1番目の要素(value)でソート(valueの昇順)
>>>list_c = sorted(dict_a.items(), key=lambda x: x[1])
>>>list_c
[('ff07', 6), ('ff10', 9), ('ff08', 11)]
注意点

sorted()は、 入力とは別のリストを生成するので、 入力はそのままで変化しない。 また、元リストとは別にリストを生成するので、 sort()と比較すると、わずかにメモリ効率が悪いです。

>>>list_a = [5,3,8]
>>>list_b = sorted(list_a)
>>>list_b
[3, 5, 8]

#元リスト
>>>list_a
[5, 3, 8]

参考資料

docs.python.jp