概要(sorted の key は「並べ替えの基準」を自由に設計するための心臓部)
sorted は「イテラブルを並べ替えて新しいリストを返す」関数で、key は「要素から並べ替えの基準値を取り出す関数」を指定します。つまり「何を基準に並べるか」を1行で決められます。数値の絶対値、文字列の小文字化、タプルの特定フィールド、辞書のあるキー、クラスの属性など、key を変えるだけで自在にソートできます。Python のソートは安定で高速(Timsort)なので「第2基準」を重ねる設計も簡単です。
基本の使い方(ここが重要)
数値や文字列を単純な基準で並べる(abs、str.lower など)
nums = [-4, -2, 1, 3, -5, 2]
print(sorted(nums, key=abs)) # 絶対値で昇順
words = ["Banana", "apple", "Cherry"]
print(sorted(words, key=str.lower)) # 大文字小文字を無視して並べる
Pythonkey は「要素→基準値」の関数なら何でも良いです。CPU コストの軽い基準を選ぶと高速にまとまります。
辞書やタプルを「特定の項目」で並べる(itemgetter が便利)
from operator import itemgetter
pairs = [("alice", 25), ("bob", 30), ("charlie", 20)]
print(sorted(pairs, key=itemgetter(1))) # 2番目(年齢)で昇順
rows = [{"name": "alice", "score": 70},
{"name": "bob", "score": 85}]
print(sorted(rows, key=itemgetter("score"))) # "score" キーで昇順
Pythonitemgetter はラムダより短く高速なことが多く、読みやすさも高いです。
クラスのリストは「属性」を基準に
class P:
def __init__(self, name, score):
self.name = name
self.score = score
people = [P("alice", 92), P("bob", 85)]
print([p.name for p in sorted(people, key=lambda p: p.score)])
Pythonkey では属性を取り出すだけ。必要なら複数属性をタプルで返して第2基準まで一度に書けます。
重要ポイントの深掘り(複数基準・安定ソート・性能・API 差分)
複数基準(第2・第3基準)を「タプルで返す」
students = [
{"name": "alice", "score": 85},
{"name": "bob", "score": 85},
{"name": "cara", "score": 92},
]
# まず score 昇順、同点なら name 昇順
print(sorted(students, key=lambda r: (r["score"], r["name"])))
Pythonタプル比較は第1要素→第2要素…の順に自動で評価されるため、複数条件の表現が短く正確になります。
安定ソートの性質を活かす(段階ソートのテクニック)
Python のソートは安定なので、「あとから並べた基準」が優先されます。逆順にソートを重ねると読みやすく書けます。
rows = [{"name":"bob","score":85},
{"name":"alice","score":85},
{"name":"cara","score":92}]
rows = sorted(rows, key=lambda r: r["name"]) # 第2基準
rows = sorted(rows, key=lambda r: r["score"]) # 第1基準(安定なので名前順は維持)
print(rows)
Pythonただし一発でタプル key を返す方がミスが少なく、計算も1回で済みます。
速度の勘所(キー計算の前取り・itemgetter・重い処理を避ける)
- キー関数が重いとソート全体が遅くなります。属性や関数参照はループ外でローカルに束縛すると高速化します。
- ラムダより itemgetter/attrgetter が速い場面が多く、読みやすいです。
- 重い正規表現や I/O を key に入れない。前処理で計算しておくか、軽い値に変換してから並べる。
import math
sin = math.sin # 参照の前取り
print(sorted(range(1000), key=sin))
Pythonsorted と list.sort の違い(不変性/破壊的)
- sorted(iterable, …) は「新しいリスト」を返して元データを変えません。
- list.sort(…) は「そのリスト自体」を並べ替えます(破壊的)。戻り値は None。
nums = [3,1,2]
sorted_nums = sorted(nums) # 新リスト
nums.sort() # 破壊的
Python目的に応じて使い分けます。元データを保ちたいなら sorted、一度きりで良いなら sort が若干高速です。
実務での使いどころ(テキスト整列・辞書整列・複合キー・安全な昇降順)
大文字小文字を無視した辞書の「値」ソートと整形
items = {"Banana": 3, "apple": 1, "Cherry": 2}
# 値で昇順、同値ならキーの小文字化で昇順
sorted_items = sorted(items.items(), key=lambda kv: (kv[1], kv[0].lower()))
print(sorted_items) # [('apple',1), ('Cherry',2), ('Banana',3)]
Python表示用に並べつつ、大小を無視した読みやすい整列ができます。
複合キーで「降順・昇順」を混ぜる
降順は reverse=True でも良いですが、「一部だけ降順」を混ぜたいときは符号反転などで工夫します。
rows = [{"price": 100, "rating": 4.5},
{"price": 200, "rating": 4.5},
{"price": 150, "rating": 4.8}]
# rating 降順、price 昇順
print(sorted(rows, key=lambda r: (-r["rating"], r["price"])))
Python数値なら負にするのが簡単。文字列の降順混在は「2段階ソート+安定性」や「キーを事前に整形」で対応します。
日付・時刻・バージョンなど「文字列を正規の型に」してから並べる
from datetime import datetime
logs = [{"ts":"2025-12-15 09:00"}, {"ts":"2025-12-14 18:00"}]
fmt = "%Y-%m-%d %H:%M"
print(sorted(logs, key=lambda r: datetime.strptime(r["ts"], fmt)))
Python比較に適した「型」へ変換してから並べれば、意図通りの順序になります。バージョンはパーツ分割してタプルにするのが定石です。
欠損値(None)を安全に扱う(カスタムキーで末尾へ送る)
rows = [{"name": "alice", "score": 85},
{"name": "bob", "score": None},
{"name": "cara", "score": 92}]
# None を最後に、数値で昇順
safe_key = lambda r: (r["score"] is None, r["score"] if r["score"] is not None else float("inf"))
print(sorted(rows, key=safe_key))
Python比較不可な組み合わせ(None と数値)を直接比較させず、ブール+代替値のタプルで安全に並べます。
例題で身につける(定番から一歩先まで)
例題1:辞書リストを「2基準」で並べる(スコア優先→名前)
data = [{"name":"Bob","score":85},
{"name":"Alice","score":85},
{"name":"Cara","score":92}]
print(sorted(data, key=lambda r: (r["score"], r["name"])))
Python例題2:文字列を「数字入りでも自然順」に近づける
import re
def natural_key(s):
# 数字を分割して int、他は小文字化
parts = re.findall(r"\d+|[^\d]+", s)
return tuple(int(p) if p.isdigit() else p.lower() for p in parts)
files = ["file2.txt", "file10.txt", "file1.txt"]
print(sorted(files, key=natural_key)) # file1, file2, file10
Python例題3:辞書の items を「値降順→キー昇順」
from operator import itemgetter
d = {"a": 2, "b": 2, "c": 3}
print(sorted(d.items(), key=lambda kv: (-kv[1], kv[0])))
Python例題4:クラスの並べ替えで attrgetter を使う
from operator import attrgetter
class P:
def __init__(self, name, score):
self.name, self.score = name, score
people = [P("alice", 92), P("bob", 85)]
print([p.name for p in sorted(people, key=attrgetter("score"))])
Pythonまとめ
sorted の key は「要素からソート基準を取り出す関数」で、並べ替えの設計をすべて決める重要箇所です。単一基準はもちろん、タプルで複数基準、安定ソートの性質を活かした段階ソート、負符号による部分降順、型変換による正しい比較、None の安全処理まで、key を適切に設計すれば実務の並べ替えは短く正確に書けます。性能は「キー計算を軽く・前取りする」ことがコツ。目的に応じて sorted(非破壊)と sort(破壊)を使い分け、itemgetter/attrgetter で読みやすく高速に仕上げましょう。
