Python | データ構造:list.sort

Python
スポンサーリンク

list.sort の概要(リストを“その場で”並べ替える)

list.sort は、リストの要素を指定した順序で並べ替えるメソッドです。元のリストを直接変更するインプレース操作で、戻り値は None(何も返しません)。基本は昇順、引数で降順や並べ替え基準を指定できます。

nums = [5, 2, 9, 1]
nums.sort()
print(nums)  # [1, 2, 5, 9]
Python

基本構文と引数(ここが重要)

reverse で降順にする

reverse=True を渡すと降順になります。インプレースなので、呼び出し後のリストが更新されます。

nums = [5, 2, 9, 1]
nums.sort(reverse=True)
print(nums)  # [9, 5, 2, 1]
Python

key で“並べ替え基準”を指定する

key=関数 を渡すと、各要素にその関数を適用した値を並べ替えの指標として使います。複雑な並べ替えを簡潔に書ける重要機能です。

words = ["Zoo", "apple", "Banana"]
words.sort(key=str.lower)   # 大小無視のあいうえお順
print(words)  # ['apple', 'Banana', 'Zoo']
Python

sorted との違い(インプレースか、新しいリストか)

sort は“破壊的”、sorted は“非破壊”

  • list.sort(): 元のリストを変更し、戻り値は None。
  • sorted(iterable): 新しい並べ替え済みリストを返し、元は変えない。
nums = [4, 2, 9, 1]
res = sorted(nums)   # 新しいリスト
print(nums)  # [4, 2, 9, 1]
print(res)   # [1, 2, 4, 9]
Python

元の順序を保持したい場合や、タプル・集合・辞書のキーなど“リスト以外”を並べ替えたい場合は sorted を使うのが自然です。


現場で役立つ key の設計(重要ポイントを深掘り)

長さや絶対値など「派生値」で並べる

words = ["tea", "espresso", "latte"]
words.sort(key=len)      # 文字数順
print(words)  # ['tea', 'latte', 'espresso']

nums = [-10, 3, -2, 8]
nums.sort(key=abs)       # 絶対値順
print(nums)  # [3, -2, 8, -10]
Python

複合条件は「タプルキー」にする

タプルは辞書順で比較されます。先に第一条件、同点なら第二条件…と自然に並びます。

items = [("coffee", 350), ("tea", 280), ("juice", 280)]
items.sort(key=lambda x: (x[1], x[0]))  # 価格→名前
print(items)
# [('juice', 280), ('tea', 280), ('coffee', 350)]
Python

安定ソートを活かす(同点の元順序は保たれる)

Python の sort は安定です。先に“弱い条件”で並べ、次に“強い条件”で並べ替えると、前の条件の相対順序を保ったまま整います。

rows = [
    ("A", 2), ("B", 1), ("C", 2), ("D", 1)
]
rows.sort(key=lambda x: x[0])  # 名前順
rows.sort(key=lambda x: x[1])  # 点数順(同点の名前順が維持される)
print(rows)
# [('B', 1), ('D', 1), ('A', 2), ('C', 2)]
Python

よくある落とし穴と安全策

戻り値は None(チェーンしない)

nums = [3, 1, 2]
result = nums.sort()
print(result)  # None
# 並べ替え結果は nums 自体に反映される
Python

型が混在すると比較不能でエラー

Python 3 では異種型(例: 文字列と数値)の大小比較はできません。事前に型をそろえるか、key で比較対象を統一してください。

data = ["10", 2, "30"]
# data.sort()  # TypeError
data.sort(key=str)        # 文字列として比較
print(data)  # [2, '10', '30']  ← 表示上は混在に注意
Python

ロケールや読み仮名順は自前で定義する

日本語の“辞書順/読み順”は用途により異なるため、必要なら key に正規化関数(ひらがな化、濁点除去など)を組み込んで定義します。


例題で身につける(定番から一歩先まで)

例題1:商品を価格の昇順、同価格なら名前順

products = [
    {"name": "coffee", "price": 350},
    {"name": "tea",    "price": 280},
    {"name": "juice",  "price": 280},
]
products.sort(key=lambda p: (p["price"], p["name"]))
for p in products:
    print(p["name"], p["price"])
# tea 280 / juice 280 / coffee 350
Python

例題2:ファイル名を“数値として”自然順に

files = ["file2.txt", "file10.txt", "file1.txt"]
files.sort(key=lambda s: int(s.removeprefix("file").removesuffix(".txt")))
print(files)  # ['file1.txt', 'file2.txt', 'file10.txt']
Python

例題3:大文字小文字を無視して並べる

names = ["taro", "Hanako", "JIRO"]
names.sort(key=str.casefold)   # casefold は lower より包括的
print(names)  # ['Hanako', 'JIRO', 'taro']
Python

例題4:安定ソートで二段階の整列

scores = [
    {"name": "A", "math": 80, "eng": 70},
    {"name": "B", "math": 80, "eng": 85},
    {"name": "C", "math": 90, "eng": 60},
]
scores.sort(key=lambda x: x["eng"])    # 英語昇順
scores.sort(key=lambda x: x["math"])   # 数学昇順(安定)
for s in scores:
    print(s["name"], s["math"], s["eng"])
# B 80 85 / A 80 70 / C 90 60
Python

パフォーマンスの考え方(規模とコストの見積もり)

計算量は概ね O(n log n)

大量データでも十分高速ですが、key 関数が重いと全体が遅くなります。key 内で高コスト処理を行う場合は、あらかじめ結果をフィールドに持たせる、または「装飾・ソート・剥がし」(Schwartzian transform)を用いて計算を一回に抑えると効果的です。

items = ["file2.txt", "file10.txt", "file1.txt"]
decorated = [(int(s[4:-4]), s) for s in items]
decorated.sort()
items = [s for _, s in decorated]
print(items)  # ['file1.txt', 'file2.txt', 'file10.txt']
Python

メモリを節約したいなら sort を選ぶ

結果のコピーが不要なら list.sort が基本。複数バージョン(元と並べ替え後)を同時に持ちたいときだけ sorted を使い分けます。


まとめ

list.sort は「元のリストをその場で並べ替える」メソッドで、reverse と key により降順や柔軟な並べ替え基準を設定できます。戻り値は None、異種型の比較は不可、Python のソートは安定であるため“段階的整列”が可能。元を残す必要があるなら sorted、インプレースで十分なら sort。key を賢く設計し、必要ならタプルキーや事前計算を使えば、初心者でも意図どおりに速く正確な並べ替えが書けます。

タイトルとURLをコピーしました