Pythonにおいてデータの並び替えは、プログラミングの根幹をなす操作の一つです。

2026年現在、膨大なデータを効率的に処理するスキルは、ソフトウェア開発においてこれまで以上に重要視されています。

その中でも sorted() 関数は、柔軟性と汎用性を兼ね備えた非常に強力な標準ツールです。

本記事では、基本的な数値や文字列のソートから、複雑なオブジェクトの並び替え、さらには実務で役立つ応用テクニックまでを詳しく紹介します。

Pythonを使い始めたばかりの方から、より効率的なコードを書きたい中級者の方まで、幅広く役立つ内容をお届けします。

Pythonのsorted関数の基本構造

まずは、sorted() 関数の基本的な使い方と、その特徴について理解を深めましょう。

sorted() は、リストやタプル、辞書などのイテラブルなオブジェクトを引数に取り、新しいリストとしてソート結果を返します。

元のオブジェクト自体を書き換えないため、元のデータを保持したまま並び替えた結果を取得したい場合に最適です。

sorted関数の基本構文

sorted() 関数の基本的な構文は以下の通りです。

Python
# 基本構文
sorted(iterable, key=None, reverse=False)

第一引数の iterable には、ソートしたいデータ集合を指定します。

key 引数や reverse 引数はオプションであり、必要に応じて動作をカスタマイズするために使用します。

リストのソートと昇順・降順

もっともシンプルな例として、数値のリストを昇順に並び替えてみましょう。

Python
numbers = [5, 2, 9, 1, 5, 6]
sorted_numbers = sorted(numbers)

print(f"元のリスト: {numbers}")
print(f"ソート後: {sorted_numbers}")
実行結果
元のリスト: [5, 2, 9, 1, 5, 6]
ソート後: [1, 2, 5, 5, 6, 9]

このように、デフォルトの状態では 数値が小さい順(昇順) に並び替えられます。

降順(大きい順)に並び替えたい場合は、引数に reverse=True を指定します。

Python
numbers = [5, 2, 9, 1, 5, 6]
descending_numbers = sorted(numbers, reverse=True)

print(descending_numbers)
実行結果
[9, 6, 5, 5, 2, 1]

sortメソッドとsorted関数の決定的な違い

Pythonには、リストを並び替える方法として list.sort() メソッドも存在します。

初心者の方が混同しやすいポイントですので、両者の違いを表で整理しましょう。

特徴sorted() 関数list.sort() メソッド
戻り値新しいソート済みリストを返すNone(元のリストを直接更新する)
元のデータ変更されない(非破壊的)変更される(破壊的)
適用対象すべてのイテラブル(タプルや辞書など)リスト型(list)のみ
主な用途元のデータを残したいときメモリ消費を抑えて高速処理したいとき

データの不変性を保ちたい場合や、リスト以外のデータ構造を扱う場合は、sorted() 関数を使用するのが一般的です。

key引数による高度なカスタマイズ

sorted() 関数の真価は、key 引数を利用したカスタムソートにあります。

key 引数には「ソートの基準を決定する関数」を渡すことができます。

絶対値や文字列の長さでソートする

例えば、数値のリストを絶対値の大きさで並び替えたい場合、組み込み関数の abs を指定します。

Python
values = [-10, 5, -2, 8, -1]
# 絶対値でソート
sorted_values = sorted(values, key=abs)

print(sorted_values)
実行結果
[-1, -2, 5, 8, -10]

また、文字列のリストを文字数(長さ)で並び替えたい場合は、len 関数を指定します。

Python
words = ["python", "java", "rust", "go", "javascript"]
# 文字数でソート
sorted_words = sorted(words, key=len)

print(sorted_words)
実行結果
['go', 'java', 'rust', 'python', 'javascript']

lambda(ラムダ式)を用いた柔軟な指定

より複雑なデータ構造を扱う際、特定の要素を基準にするために lambda(無名関数) が頻繁に使われます。

例えば、タプルのリストがあり、各タプルの2番目の要素(インデックス1)を基準にしたい場合は以下のように記述します。

Python
students = [("田中", 80), ("佐藤", 95), ("鈴木", 70)]
# 成績(2番目の要素)でソート
sorted_students = sorted(students, key=lambda x: x[1])

print(sorted_students)
実行結果
[('鈴木', 70), ('田中', 80), ('佐藤', 95)]

このように lambda を活用することで、自由自在にソートロジックを構築することが可能です。

辞書データのソート

辞書(dict)をソートする場合、少し注意が必要です。

辞書そのものを sorted() に渡すと、デフォルトでは「キー(key)」だけが取り出されてソートされます。

キーや値で辞書を並び替える

辞書の「値(value)」に基づいてソートし、その結果をリストとして取得する方法を見てみましょう。

Python
prices = {"りんご": 150, "バナナ": 100, "メロン": 1000, "みかん": 80}

# 値(価格)に基づいてソート
sorted_prices = sorted(prices.items(), key=lambda x: x[1])

print(sorted_prices)
実行結果
[('みかん', 80), ('バナナ', 100), ('りんご', 150), ('メロン', 1000)]

items() メソッドを呼び出すことで、キーと値のペアをタプルとして取得し、それを key 引数で制御しています。

2026年のモダンな開発現場では、辞書の順序が保証されていることを前提としたコードが多く見られますが、明示的なソートが必要な場面は依然として多く存在します。

operatorモジュールを用いた高速化

パフォーマンスを重視する場合、lambda よりも operator モジュールの関数を使用する方が効率的です。

特に大量のデータを処理する際は、itemgetter や attrgetter の活用が推奨されます。

itemgetterによるインデックス指定

先ほどのタプルのソートを itemgetter で書き換えてみます。

Python
from operator import itemgetter

data = [("A", 10, "Tokyo"), ("B", 5, "Osaka"), ("C", 15, "Nagoya")]
# 2番目の数値(インデックス1)でソート
sorted_data = sorted(data, key=itemgetter(1))

print(sorted_data)
実行結果
[('B', 5, 'Osaka'), ('A', 10, 'Tokyo'), ('C', 15, 'Nagoya')]

itemgetter は内部的に最適化されているため、lambda を使うよりも実行速度がわずかに向上します。

attrgetterによるオブジェクト属性の指定

独自に定義したクラスのインスタンス(オブジェクト)をソートする場合は、attrgetter が便利です。

Python
from operator import attrgetter

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price
    
    def __repr__(self):
        return f"{self.name}({self.price})"

products = [Product("PC", 120000), Product("Mouse", 5000), Product("Monitor", 30000)]
# price属性でソート
sorted_products = sorted(products, key=attrgetter('price'))

print(sorted_products)
実行結果
[Mouse(5000), Monitor(30000), PC(120000)]

複数条件によるソート(マルチレベルソート)

実務では「まずは第一の条件でソートし、同じ値であれば第二の条件で並び替えたい」というケースが頻発します。

Pythonの sorted() は、安定ソート(Stable Sort) であるという重要な特性を持っています。

安定ソートとは何か

安定ソートとは、ソートの基準となる値が同じ場合に、元の順序が維持される という性質です。

これにより、複数の条件を組み合わせてソートすることが可能になります。

複数のキーを指定する方法

最も簡単な方法は、key 引数にタプルを返す lambda を指定することです。

Python
employees = [
    {"name": "田中", "dept": "開発", "age": 30},
    {"name": "佐藤", "dept": "営業", "age": 25},
    {"name": "鈴木", "dept": "開発", "age": 25},
]

# 1番目に部署名、2番目に年齢でソート
sorted_employees = sorted(employees, key=lambda x: (x["dept"], x["age"]))

for emp in sorted_employees:
    print(emp)
実行結果
{'name': '鈴木', 'dept': '開発', 'age': 25}
{'name': '田中', 'dept': '開発', 'age': 30}
{'name': '佐藤', 'dept': '営業', 'age': 25}

この手法を使えば、複雑な優先順位を持ったデータ整列も一行でスマートに記述できます。

大規模データとパフォーマンスの考慮

2026年のデータ集計システムでは、数百万行のデータをメモリ上で扱うことも珍しくありません。

sorted() 関数は、Timsort と呼ばれる非常に高度なアルゴリズムを採用しています。

Timsortはマージソートと挿入ソートを組み合わせたもので、実世界のデータに対して驚異的な効率を発揮します。

メモリ使用量への注意

ただし、sorted() は新しいリストを作成するため、メモリ使用量が元のデータの2倍近くになる可能性があります。

もしメモリ制約が厳しい環境で、元のデータを保持する必要がない場合は、list.sort() を使用して破壊的に並び替えることを検討してください。

また、イテレータを維持したまま最小値や最大値だけを取得したい場合は、min() や max() 、あるいは heapq モジュールを検討するのがプロの選択です。

まとめ

Pythonの sorted() 関数は、シンプルながらも非常に奥が深く、使いこなすことでコードの可読性と効率を劇的に向上させることができます。

基本となる昇順・降順の操作はもちろん、key 引数を用いたカスタムソートや operator モジュールによる最適化は、実務レベルでは必須の知識です。

また、安定ソートの性質を理解し、複数条件での並び替えをマスターすれば、より高度なデータ分析やロジックの実装が可能になります。

日々のコーディングにおいて、どのソート手法が最適かを常に考える習慣をつけましょう。

この記事で紹介したテクニックを活用し、洗練されたPythonプログラムを構築してください。