Python のリストソートいろいろ
Python3 でリストのソートを行う方法をまとめます。この記事でまとめるのは以下の方法です。
- 非破壊的ソート
- 破壊的ソート
- 降順にソート
- クラスの特定の値を使ってソート
- タプルをソート
- 複数キーを使ったソート
組み込み関数の sorted()
Python の組み込み関数 sorted()
を使ってリストをソートすることが可能です。sorted()
は引数で渡されたリストのソート結果を、新しく生成した配列に格納して返します。
array = [3, 1, 4, 1, 5, 9, 2, 6]
result = sorted(array)
print(array) # [3, 1, 4, 1, 5, 9, 2, 6]
print(result) # [1, 1, 2, 3, 4, 5, 6, 9]
ソートされるリストの状態は変更されないことに注意してください。新しく生成されたリストにソート結果が格納されています。
非破壊的なソート を行いたい場合は組み込み関数の sorted()
を使いましょう。
リストの持つメソッド sort()
リスト型はソートメソッド sort()
を持ちます。これを使うことでリストの状態を書き換えてソートを行います。つまり 破壊的なソート を行います。
前述の組み込み関数 sorted()
との違いは破壊的ソートを行うかどうかです。
array = [3, 1, 4, 1, 5, 9, 2, 6]
array.sort()
print(array) # [1, 1, 2, 3, 4, 5, 6, 9]
sort()
を呼び出した array の中身が直接ソートされた結果に書き換えられています。
降順(逆順)にソートする
前述の sort()
も sorted()
も、引数で降順(逆順)にソートすることができます。reverse=True
と指定します。
array = [3, 1, 4, 1, 5, 9, 2, 6]
result = sorted(array, reverse=True)
print(result) # [9, 6, 5, 4, 3, 2, 1, 1]
array = [3, 1, 4, 1, 5, 9, 2, 6]
array.sort(reverse=True)
print(array) # [9, 6, 5, 4, 3, 2, 1, 1]
クラスの特定の値を使ってソート
クラスが格納されたリストをソートしたい場合はいくつか方法があります。
key に attrgetter を使う
ソート時に引数で key を指定します。 attrgetter
でソートする際に用いるキーとなる属性を指定できます。たとえば以下のようなクラスが格納されたリストをソートする例を考えます。
class Human:
def __init__(self, name, age):
self.name = name
self.age = age
名前と年齢の2つの値を持つクラスです。このクラスのリストを年齢でソートする場合は以下のように書けます。
from operator import itemgetter
a = Human('taro', 20)
b = Human('jiro', 10)
c = Human('hanako', 15)
array = [a, b, c]
# age をキーにソート
result = sorted(array, key=attrgetter('age'))
# array.sort(key=attrgetter('age'))
for h in result:
print(vars(h))
# {'name': 'jiro', 'age': 10}
# {'name': 'hanako', 'age': 15}
# {'name': 'taro', 'age': 20}
itemgetter
を import するのをお忘れなく。sort()
を使う場合も同じく key を指定してください。
key に lamda を使う
lambda
を使って直接比較するキーを取り出す式を指定できます。
a = Human('taro', 20)
b = Human('jiro', 10)
c = Human('hanako', 15)
array = [a, b, c]
result = sorted(array, key=lambda h: h.age)
# array.sort(key=lambda h: h.age)
for h in result:
print(vars(h))
# {'name': 'jiro', 'age': 10}
# {'name': 'hanako', 'age': 15}
# {'name': 'taro', 'age': 20}
タプルをソートする
タプルのリストと同様にソートできます。ただしタプルは変更不可なので soted()
しか使えません。
sorted()
tup = (3, 1, 4, 1, 5)
result = sorted(tup)
print(result) # [1, 1, 3, 4, 5]
print(tuple(result)) # (1, 1, 3, 4, 5)
タプルに対して sorted()
を使ってソートすると、リストでソート結果が返されます。結果はリストで返されるので、タプルにしたければご自由に。
複数キーでのソート
複数キーでソートするには、タプルにした値をキーにソートします。タプルのソートは1つ目の値から順番に比較していくので、結果いい感じに複数キーでのソートになります。
a = Human('taro', 20)
b = Human('taro', 10)
c = Human('hanako', 15)
array = [a, b, c]
result = sorted(array, key=lambda h: (h.name, h.age))
for h in result:
print(vars(h))
# {'name': 'hanako', 'age': 15}
# {'name': 'taro', 'age': 10}
# {'name': 'taro', 'age': 20}
この方法だと複合キーすべてに対して昇順(降順)になります。個別のキーに対して昇順(降順)を指定したい場合、優先度の低いキー順にソートを複数回実行すればよいです。
もちろん処理コストは余計にかかります。
a = Human('taro', 20)
b = Human('taro', 10)
c = Human('hanako', 15)
array = [a, b, c]
array.sort(key=attrgetter('age'))
array.sort(key=attrgetter('name'))
for h in array:
print(vars(h))
# {'name': 'hanako', 'age': 15}
# {'name': 'taro', 'age': 10}
# {'name': 'taro', 'age': 20}
以上。
コメントを書く