Pythonでリストの要素をソート(並べ替え)するには以下2つの関数があります。
- listのメソッド: list.sort()
- 標準組込み関数: sorted(iterable)
今回は、これらの違いと使い方についてまとめます。
list.sort()、sorted()の違い
それぞれの違いは下記の通りです。
関数名 | 内容 |
---|---|
list.sort() |
|
sorted() |
|
[Python] イテレータとイテラブルについて
以下、それぞれの関数の詳細について記載します。
list.sort()
リストをインプレースで(デフォルトで)昇順に並び替えます。返却値はNoneです。
リストのメソッドなので、リスト以外は使えません。
※第二引数以降のkey, reverseについては後述。
list.sort(*, key=None, reverse=False)
例を以下に示します。
>>> a = [2, 0, 5, 1, 9]
>>> a.sort() #返却値はNoneなので何も表示されません
>>> a
[0, 1, 2, 5, 9] #元のデータは変わっています
sorted()
任意のイテラブルを引数に設定することが出来ます。返却値はソートされたリストです(デフォルトは昇順)。
尚、元のデータは変わりません。
※第二引数以降のkey, reverseはsort()と同様で後述します。
sorted(iterable, *, key=None, reverse=False)
例を以下に示します。
>>> a= [2, 0, 5, 1, 9]
>>> sorted(a) #ソートされた新たなリストが返却
[0, 1, 2, 5, 9]
>>> a
[2, 0, 5, 1, 9] #元のデータは変わっていません
sorted()はlist以外のイテラブル(例えば辞書)でも使えます。
尚、タプルや辞書の様に要素の中身が2つ以上ある場合は、一番左の要素でソートされます。
以下は辞書の例です。
#辞書を設定するとkeyでソートされます
>>> dic = {'e': 1, 'b': 4, 'd': 2, 'a': 5, 'c': 3}
>>> sorted(dic)
['a', 'b', 'c', 'd', 'e']
#dic.keys()を使っても同様の結果
>>> sorted(dic.keys())
['a', 'b', 'c', 'd', 'e']
#dic.values()を使うと、辞書のvalueでソートされます
>>> sorted(dic.values())
[1, 2, 3, 4, 5]
#dic.items()を使うと、辞書データをタプルを要素としたリストを返却
#後述するkeyパラメータに何も設定をしないと、タプルの一番左の要素でソートされます
>>> sorted(dic.items())
[('a', 5), ('b', 4), ('c', 3), ('d', 2), ('e', 1)]
Key function
keyパラメータは、要素をソートする際にデータを加工したり、ソートする要素を指定する為の関数を設定します。
例その1:単語の大文字・小文字を区別なく並べ替える
keyパラメータにkey=str.lowerを設定すると、文字列が全て小文字に変換されてからソートされます。
>>> sorted('How do you get to the Train Station?'.split(" "), key = str.lower)
['do', 'get', 'How', 'Station?', 'the', 'to', 'Train', 'you']
例その2:タプルの二番目の値でソートしたい場合
ambda関数を使うことも可能です。
以下は、辞書のitems()メソッドで得られるタプルのうち、二番目の要素であるvalueでソートした場合の例です。
>>> dic = {'e': 1, 'b': 4, 'd': 2, 'a': 5, 'c': 3}
>>> sorted(dic.items(), key = lambda x:x[1])
[('e', 1), ('d', 2), ('c', 3), ('b', 4), ('a', 5)]
尚、この処理はOperatorモジュール(この場合はitemgetter()メソッド)を使うと、もう少し簡単に書けます。
>>> from operator import itemgetter
>>> sorted(dic.items(), key = itemgetter(1))
[('e', 1), ('d', 2), ('c', 3), ('b', 4), ('a', 5)]
ちなみに公式によると、itemgetter()を使った場合の方が高速であると記載がありますが、どのくらい違うのか試してみました。
<実験条件>
ソート対象データ | 3つの要素(’ランダムな5文字’,’ランダムな5文字’, 1〜10000のランダムな数値)を含んだタプルを10^n個生成しリスト化 |
データ数 | 10^1個〜10^6個 |
結果を下図に示します。横軸にデータ数、縦軸にソート時間を示しており、両軸とも基底10の対数値をとっています。公式に記載の通りitemgetter()を使うほうが高速のように見えますが、、微妙な感じです。(コードはこちらにアップロードしています)
reverseパラメータ
reverseパラメータは昇順でソートするか、降順でソートするかを設定します。
- reverse = False : 昇順(デフォルト)
- reverse = True:降順
例を以下に示します。
#list.sort()メソッドの場合
>>> a = [2, 0, 5, 1, 9]
>>> a.sort(reverse = True)
>>> a
[9, 5, 2, 1, 0]
#sorted()関数の場合
>>> a = [2, 0, 5, 1, 9]
>>> sorted(a, reverse = True)
[9, 5, 2, 1, 0]
確認した環境
- OS: Ubuntu 20.04LTS
- Python: ver3.9.1
まとめ
今回は、データの並べ替えについてまとめました。
- list.sort()とsorted()の使い方と違い
- キーワード引数key, reverseの使い方