Pythonでリストを逆順にしたい場面は、降順に並べ替えたい場合と、現在の順序をそのままひっくり返したい場合の2通りがあります。
本記事では初心者の方にも分かりやすく、この違いを整理しながら、3つの方法を実例付きで丁寧に解説します。
Pythonのリストを逆順にする基本
リストを「逆順」にする作業には大きく2種類あります。
1つは並べ替えの規則に従って大きいものから小さいものへと「降順にソート」すること、もう1つは現在の並び順をそのまま「反転」することです。
この2つは似ているようで目的が異なるため、使うべきメソッドも変わります。
本記事では順を追って違いを明確にし、使い分けを迷わないように整理します。
逆順ソートと反転の違い
逆順ソートは、要素の値に基づき大きい順(降順)に並べ替えます。
例えばリストが[3, 1, 4, 1, 5]
なら、降順ソートの結果は[5, 4, 3, 1, 1]
になります。
この操作では値の大小関係が使われます。
反転は、現在の並び順をそのまま裏返します。
同じ[3, 1, 4, 1, 5]
を反転すると[5, 1, 4, 1, 3]
になり、値の大小は考慮されません。
すでに昇順になっているリストを反転すれば、結果的に降順と同じになりますが、昇順でないリストに対しては「降順ソート」と「反転」で違う結果になります。
3つの方法の選び方
逆順にする代表的な3つの方法は、目的に応じて次のように選びます。
どれを使えばよいか迷った時は、まず「降順に値で並べたいのか」「順序を単純にひっくり返したいのか」を決めると判断が早まります。
- 値で降順に並べたい場合は
list.sort(reverse=True)
またはsorted(iterable, reverse=True)
を使います。前者は元のリストを書き換え、後者は新しいリストを返します。 - 現在の順序をそのまま反転したい場合は
list.reverse()
を使います。これは並べ替えではありません。 - コピーを作りつつ反転したい場合はスライス
[::-1]
、イテレータで反転順に走査したい場合はreversed()
が補助的に使えます。
次の表は特性の概要です。
方法 | 目的 | 破壊的変更 | 戻り値 | 主な用途 |
---|---|---|---|---|
list.sort(reverse=True) | 値に基づく降順ソート | あり | None | 元のリストを直接降順にしたい時 |
sorted(iterable, reverse=True) | 値に基づく降順ソート | なし | 新しいリスト | 元データを残しつつ降順が欲しい時 |
list.reverse() | 現在の順序を反転 | あり | None | 並びを単純にひっくり返したい時 |
方法1 list.sort(reverse=True)で降順ソート
list.sort()
はリスト専用のメソッドで、元のリスト自体を書き換えます。
reverse=True
を指定すると降順になります。
最も直接的で、余計なメモリを使わないのが利点です。
使い方と例
基本的な使い方は次のとおりです。
# 降順にソートする基本例
numbers = [3, 1, 4, 1, 5]
numbers.sort(reverse=True) # 元のリストを降順に並べ替える(破壊的)
print(numbers) # => [5, 4, 3, 1, 1]
[5, 4, 3, 1, 1]
key
引数を使うと、比較の基準を指定できます。
例えば、大小関係ではなく大文字小文字を無視して降順に並べたい場合は次のようにします。
# 文字列を大文字小文字を無視して降順にソート
words = ["Apple", "banana", "cherry", "Date"]
# key=str.lower で比較用の値を小文字化してから比較する
words.sort(key=str.lower, reverse=True)
print(words) # => ['Date', 'cherry', 'banana', 'Apple']
['Date', 'cherry', 'banana', 'Apple']
注意点 破壊的変更と戻り値
list.sort()
は破壊的(インプレース)に動作し、戻り値はNone
です。
戻り値に結果リストが入っていると勘違いしがちなので注意してください。
numbers = [2, 7, 1]
result = numbers.sort(reverse=True) # 戻り値は None
print("numbers:", numbers) # 並びが変わっている
print("result:", result) # None なので要注意
numbers: [7, 2, 1]
result: None
また、Python 3では数値と文字列が混在するような比較不能な要素を含むリストはソートできません。
例えば[1, "2"]
をソートするとTypeError
になります。
要素の型をそろえる、あるいはkey
で比較基準を定めるなどの対処が必要です。
なお、list.sort()
の計算量は平均でO(n log n)で、ソートは安定(等価な要素の相対順序を保持)です。
方法2 sorted(…, reverse=True)で降順ソート
sorted()
はリストに限らず任意のイテラブルに対して使える組み込み関数で、新しいリストを返します。
元のデータを変更したくない場合に最適です。
使い方と例
基本的な使い方は次のとおりです。
# 元のリストを残しつつ降順リストを得る
nums = [3, 1, 4, 1, 5]
desc = sorted(nums, reverse=True) # 新しいリストが返る(非破壊)
print("元のリスト:", nums)
print("降順リスト:", desc)
元のリスト: [3, 1, 4, 1, 5]
降順リスト: [5, 4, 3, 1, 1]
key
引数も同様に使えます。
# 文字列を長さで降順にソート
fruits = ["fig", "watermelon", "pear", "apple"]
by_length_desc = sorted(fruits, key=len, reverse=True)
print(by_length_desc) # => ['watermelon', 'apple', 'pear', 'fig']
['watermelon', 'apple', 'pear', 'fig']
元のリストを残したい時
sorted()
は常に新しいリストを返すため、元データの保全が重要な処理や、もとの順序での処理も並行して行いたい場合に有効です。
例えば元の順序のまま走査した後、降順の結果を別途使うといった使い分けが簡単にできます。
sorted()
も計算量はO(n log n)で安定ソートです。
メモリは結果の新しいリスト分を追加で消費します。
方法3 list.reverse()で順序を反転
list.reverse()
はソートではなく、現在の並びをそのまま逆順にします。
計算量はO(n)で、元のリストが書き換わります。
使い方と例
基本的な使い方は次のとおりです。
# 現在の順序を反転する
numbers = [3, 1, 4, 1, 5]
numbers.reverse() # 破壊的に反転する
print(numbers) # => [5, 1, 4, 1, 3]
[5, 1, 4, 1, 3]
戻り値はNone
なので、代入して使わないように注意します。
data = [10, 20, 30]
res = data.reverse() # 戻り値は None
print("data:", data)
print("res:", res)
data: [30, 20, 10]
res: None
すでに昇順であるリストをreverse()
で反転すると降順と同じ結果になりますが、そうでないリストに対しては「降順ソート」と「反転」で結果が異なる点に注意してください。
スライス[::-1]やreversedとの違い
順序の反転には、list.reverse()
のほかにスライス[::-1]
と組み込み関数reversed()
もよく使われます。
それぞれ性質が異なるため、用途に応じて使い分けます。
list.reverse()
は破壊的に反転します。追加のメモリ消費が少なく高速です。lst[::-1]
は新しいリストを返します。元のリストは変えずに反転したい時に向いています。reversed(lst)
は反転順に要素を返すイテレータを返します。イテレータは遅延評価され、必要な要素だけを順に取り出せるためメモリ効率が良いです(ただしlist(reversed(lst))
とすれば新しいリストが生成されます)。
比較のための実例を示します。
# 反転の3つの手段の違い
items = [1, 2, 3, 4]
# 1) スライス: 新しいリストを作る(非破壊)
rev_slice = items[::-1]
# 2) reversed: 反転順のイテレータ(非破壊)
rev_iter_list = list(reversed(items)) # すぐ使いたい場合は list(...) にする
# 3) list.reverse: 破壊的に反転
items.reverse()
print("rev_slice:", rev_slice)
print("rev_iter_list:", rev_iter_list)
print("items(破壊的反転後):", items)
rev_slice: [4, 3, 2, 1]
rev_iter_list: [4, 3, 2, 1]
items(破壊的反転後): [4, 3, 2, 1]
反転順でループしたいだけなら、イテレータをそのまま使うと効率的です。
# reversed をそのままループに使う(コピーを作らない)
for x in reversed(range(5)): # range もシーケンスなので reversed 可能
print(x, end=" ")
print() # 改行
4 3 2 1 0
なお、[::-1]
は新しいリストを生成するため、その分のメモリを消費します。
大きなリストではlist.reverse()
やreversed()
の方がメモリ効率が良い場合があります。
まとめ
本記事では、Pythonでリストを逆順にする3つの方法を、目的別に整理して解説しました。
値に基づいて大きい順に並べたい場合はlist.sort(reverse=True)
またはsorted(..., reverse=True)
を使います。
元のリストを書き換えてよければlist.sort()
、元データを残したいならsorted()
が適しています。
現在の並びをそのままひっくり返したいだけならlist.reverse()
が最も簡単で高速です。
補助的に、コピーを作る[::-1]
や、メモリ効率の良いreversed()
も使い分けると便利です。
用途と性質を理解しておけば、迷わず最短で意図した逆順処理が書けるようになります。