【Python】リストの要素をソート(list.sort、sorted)

Python リスト 組込み型

Pythonにはデータ要素をソート(並べ替え)する関数が2つあります。

  • list.sort():リストのメソッド。データはインプレースに変更されます
  • sorted(iterable):任意のイテラブルをソートできます

今回は、これらの違いと使い方についてまとめます。
# 2020/1/24 記事更新

確認した環境

  • OS: Ubuntu 16.04LTS
  • Python: ver3.7.4

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:タプルの二番目の値でソートしたい場合

この場合は、lambda関数を使って書けます。
以下は、辞書の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()を使うほうが高速のように見えますが、、微妙な感じです。(コードはこちらにアップロードしています)

sort関数のkeyパラメータ比較

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]

まとめ

今回は、データの並べ替えについてまとめました。

  • list.sort()とsorted()の使い方と違い
  • キーワード引数key, reverseの使い方

Learn more...

書籍でもう少し詳しく学びたい場合はこちらもどうぞ。筆者もかなり参考にさせてもらっています!

シェアする
ひびきをフォローする
Hbk project