Python リストのsort()とは?並び替えの基本操作
Python初心者向けにlist.sort()メソッドの使い方を詳しく解説。昇順・降順ソート、カスタムキー関数、sorted()との違い、実用的な並び替え例を説明します。
Pythonでリストの並び替えに困ったことはありませんか?
みなさん、データを扱うプログラミングをしていると、リストの要素を順序立てて並び替えたい場面に出会いますよね。
「リストをきれいに並び替えたい」 「大きい順、小さい順にデータを整理したい」 「sort()って何?どう使うの?」
このような疑問を持ったことはありませんか?
実は、Pythonのsort()
メソッドを使えば、リストの要素を簡単かつ効率的に並び替えることができるんです。
この記事では、Python初心者の方向けにsort()
メソッドの基本的な使い方から応用的な活用法まで詳しく解説します。
データの整理がもっと楽になりますよ!
sort()メソッドとは?
まず、sort()
メソッドの基本的な概念から理解していきましょう。
これを理解すると、データの並び替えがとても身近に感じられます。
sort()の基本概念
sort()
メソッドは、リストの要素をその場で並び替えるリストの組み込みメソッドです。
簡単に言うと、リストの中身を整理整頓してくれる便利な機能なんです。 元のリストが直接変更され、新しいリストは作成されません。
デフォルトでは昇順(小さい順)で並び替えられます。
基本的な構文
基本的な使い方はとてもシンプルです。
リスト.sort(key=None, reverse=False)
パラメータの説明は以下の通りです。
key
: ソートのキーを指定する関数(省略可能)reverse
:True
で降順、False
で昇順(デフォルト)
これだけ覚えておけば、基本的な並び替えはできますよ。
基本的な使い方
それでは、実際にsort()
メソッドを使ってみましょう。
まずは基本的な使い方から始めます。
数値の並び替え
数値のリストを並び替える方法をご紹介します。
# 昇順(小さい順)での並び替えnumbers = [3, 1, 4, 1, 5, 9, 2, 6]print(f"元のリスト: {numbers}")
numbers.sort()print(f"昇順ソート後: {numbers}") # [1, 1, 2, 3, 4, 5, 6, 9]
# 降順(大きい順)での並び替えnumbers = [3, 1, 4, 1, 5, 9, 2, 6]numbers.sort(reverse=True)print(f"降順ソート後: {numbers}") # [9, 6, 5, 4, 3, 2, 1, 1]
このコードでは、数値のリストを昇順と降順で並び替えています。
reverse=True
を指定すると、大きい順に並び替えられます。
実行結果:
元のリスト: [3, 1, 4, 1, 5, 9, 2, 6]
昇順ソート後: [1, 1, 2, 3, 4, 5, 6, 9]
降順ソート後: [9, 6, 5, 4, 3, 2, 1, 1]
とても簡単に並び替えができましたね。
文字列の並び替え
文字列のリストも同様に並び替えることができます。
# アルファベット順での並び替えfruits = ["banana", "apple", "cherry", "date"]print(f"元のリスト: {fruits}")
fruits.sort()print(f"アルファベット順: {fruits}") # ['apple', 'banana', 'cherry', 'date']
# 逆アルファベット順fruits = ["banana", "apple", "cherry", "date"]fruits.sort(reverse=True)print(f"逆アルファベット順: {fruits}") # ['date', 'cherry', 'banana', 'apple']
# 日本語の並び替えjapanese_words = ["さくら", "あじさい", "ひまわり", "うめ"]japanese_words.sort()print(f"日本語ソート: {japanese_words}") # ['あじさい', 'うめ', 'さくら', 'ひまわり']
このコードでは、英語と日本語の文字列を並び替えています。 文字列は文字コード順で並び替えられます。
実行結果:
元のリスト: ['banana', 'apple', 'cherry', 'date']
アルファベット順: ['apple', 'banana', 'cherry', 'date']
逆アルファベット順: ['date', 'cherry', 'banana', 'apple']
日本語ソート: ['あじさい', 'うめ', 'さくら', 'ひまわり']
日本語も問題なくソートできます。
sort()とsorted()の違い
重要な違いを理解しておきましょう。
# sort():元のリストを変更original_list = [3, 1, 4, 1, 5]print(f"元のリスト: {original_list}")
original_list.sort()print(f"sort()後の元リスト: {original_list}") # [1, 1, 3, 4, 5]
# sorted():新しいリストを作成original_list = [3, 1, 4, 1, 5]print(f"元のリスト: {original_list}")
sorted_list = sorted(original_list)print(f"sorted()の結果: {sorted_list}") # [1, 1, 3, 4, 5]print(f"元のリスト(変更なし): {original_list}") # [3, 1, 4, 1, 5]
# 戻り値の違いnumbers = [3, 1, 4]sort_result = numbers.sort() # sort()はNoneを返すprint(f"sort()の戻り値: {sort_result}") # Noneprint(f"numbers: {numbers}") # [1, 3, 4]
numbers = [3, 1, 4]sorted_result = sorted(numbers) # sorted()は新しいリストを返すprint(f"sorted()の戻り値: {sorted_result}") # [1, 3, 4]
このコードでは、sort()
とsorted()
の重要な違いを示しています。
sort()
は元のリストを変更し、sorted()
は新しいリストを作成します。
実行結果:
元のリスト: [3, 1, 4, 1, 5]
sort()後の元リスト: [1, 1, 3, 4, 5]
元のリスト: [3, 1, 4, 1, 5]
sorted()の結果: [1, 1, 3, 4, 5]
元のリスト(変更なし): [3, 1, 4, 1, 5]
sort()の戻り値: None
sorted()の戻り値: [1, 3, 4]
用途に応じて使い分けることが大切です。
key引数を使ったカスタムソート
key
引数を使うと、カスタムの並び替えルールを指定できます。
これができると、より柔軟な並び替えが可能になります。
文字列の長さでソート
文字列の長さで並び替える例を見てみましょう。
words = ["python", "java", "c", "javascript", "go"]print(f"元のリスト: {words}")
# 文字列の長さでソートwords_by_length = words.copy() # 元のリストを保持words_by_length.sort(key=len)print(f"長さ順: {words_by_length}")
# 長さの降順words_by_length = words.copy()words_by_length.sort(key=len, reverse=True)print(f"長さ降順: {words_by_length}")
このコードでは、key=len
を指定して文字列の長さで並び替えています。
len
関数が各要素の長さを計算してくれます。
実行結果:
元のリスト: ['python', 'java', 'c', 'javascript', 'go']
長さ順: ['c', 'go', 'java', 'python', 'javascript']
長さ降順: ['javascript', 'python', 'java', 'go', 'c']
短い文字列から長い文字列へと並び替えられました。
大文字小文字を無視したソート
大文字小文字を区別せずに並び替える方法です。
names = ["Alice", "bob", "Charlie", "david"]print(f"元のリスト: {names}")
# 通常のソート(大文字小文字を区別)normal_sort = names.copy()normal_sort.sort()print(f"通常ソート: {normal_sort}")
# 大文字小文字を無視したソートcase_insensitive = names.copy()case_insensitive.sort(key=str.lower)print(f"大文字小文字無視: {case_insensitive}")
このコードでは、key=str.lower
を指定して大文字小文字を無視したソートを行っています。
str.lower
が各文字列を小文字に変換して比較します。
実行結果:
元のリスト: ['Alice', 'bob', 'Charlie', 'david']
通常ソート: ['Alice', 'Charlie', 'bob', 'david']
大文字小文字無視: ['Alice', 'bob', 'Charlie', 'david']
大文字小文字を無視すると、より自然な順序になりますね。
数値の絶対値でソート
負の数を含むリストを絶対値で並び替えてみましょう。
numbers = [-5, 2, -8, 1, 3, -1]print(f"元のリスト: {numbers}")
# 絶対値でソートabs_sorted = numbers.copy()abs_sorted.sort(key=abs)print(f"絶対値順: {abs_sorted}")
このコードでは、key=abs
を指定して絶対値で並び替えています。
abs
関数が各数値の絶対値を計算してくれます。
実行結果:
元のリスト: [-5, 2, -8, 1, 3, -1]
絶対値順: [-1, 1, 2, 3, -5, -8]
絶対値の小さい順に並び替えられました。
複雑なデータ構造のソート
実際のプログラミングでは、辞書やタプルのリストを並び替えることがよくあります。
そんな複雑なデータもsort()
で簡単に処理できます。
辞書のリストをソート
学生の情報を含む辞書のリストを並び替えてみましょう。
students = [ {"name": "田中", "age": 20, "score": 85}, {"name": "佐藤", "age": 22, "score": 92}, {"name": "鈴木", "age": 19, "score": 78}, {"name": "高橋", "age": 21, "score": 95}]
print("元のデータ:")for student in students: print(f" {student}")
# 年齢でソートstudents_by_age = students.copy()students_by_age.sort(key=lambda x: x["age"])print("年齢順:")for student in students_by_age: print(f" {student['name']}: {student['age']}歳")
# スコアでソート(降順)students_by_score = students.copy()students_by_score.sort(key=lambda x: x["score"], reverse=True)print("スコア順(高い順):")for student in students_by_score: print(f" {student['name']}: {student['score']}点")
このコードでは、lambda
関数を使って辞書の特定のキーで並び替えています。
lambda x: x["age"]
は各辞書の"age"キーの値を取得する関数です。
実行結果:
元のデータ:
{'name': '田中', 'age': 20, 'score': 85}
{'name': '佐藤', 'age': 22, 'score': 92}
{'name': '鈴木', 'age': 19, 'score': 78}
{'name': '高橋', 'age': 21, 'score': 95}
年齢順:
鈴木: 19歳
田中: 20歳
高橋: 21歳
佐藤: 22歳
スコア順(高い順):
高橋: 95点
佐藤: 92点
田中: 85点
鈴木: 78点
辞書のリストも簡単にソートできました。
タプルのリストをソート
座標を表すタプルのリストを並び替えてみましょう。
coordinates = [(3, 2), (1, 4), (2, 1), (1, 2)]print(f"元の座標: {coordinates}")
# x座標でソートcoords_by_x = coordinates.copy()coords_by_x.sort(key=lambda point: point[0])print(f"x座標順: {coords_by_x}")
# y座標でソートcoords_by_y = coordinates.copy()coords_by_y.sort(key=lambda point: point[1])print(f"y座標順: {coords_by_y}")
# 原点からの距離でソートcoords_by_distance = coordinates.copy()coords_by_distance.sort(key=lambda point: point[0]**2 + point[1]**2)print(f"原点からの距離順: {coords_by_distance}")
このコードでは、タプルの各要素や計算結果で並び替えています。
point[0]
はx座標、point[1]
はy座標を表します。
実行結果:
元の座標: [(3, 2), (1, 4), (2, 1), (1, 2)]
x座標順: [(1, 4), (1, 2), (2, 1), (3, 2)]
y座標順: [(2, 1), (3, 2), (1, 2), (1, 4)]
原点からの距離順: [(1, 2), (2, 1), (3, 2), (1, 4)]
複雑な計算を含む並び替えも可能です。
複数条件でのソート
複数の条件で並び替える高度な例を見てみましょう。
employees = [ ("田中", "開発部", 28, 450000), ("佐藤", "営業部", 32, 520000), ("鈴木", "開発部", 25, 380000), ("高橋", "営業部", 29, 480000), ("伊藤", "開発部", 35, 600000)]
print("元のデータ:")for emp in employees: print(f" {emp[0]} ({emp[1]}, {emp[2]}歳, {emp[3]:,}円)")
# 部署→年齢の順でソートemployees_by_dept_age = employees.copy()employees_by_dept_age.sort(key=lambda emp: (emp[1], emp[2]))print("部署→年齢順:")for emp in employees_by_dept_age: print(f" {emp[0]} ({emp[1]}, {emp[2]}歳)")
# 部署→給与の降順でソートemployees_by_dept_salary = employees.copy()employees_by_dept_salary.sort(key=lambda emp: (emp[1], -emp[3]))print("部署→給与順(給与は高い順):")for emp in employees_by_dept_salary: print(f" {emp[0]} ({emp[1]}, {emp[3]:,}円)")
このコードでは、タプルを返すkey関数で複数条件のソートを実現しています。
-emp[3]
のようにマイナスをつけることで、その項目だけ降順にできます。
実行結果:
元のデータ:
田中 (開発部, 28歳, 450,000円)
佐藤 (営業部, 32歳, 520,000円)
鈴木 (開発部, 25歳, 380,000円)
高橋 (営業部, 29歳, 480,000円)
伊藤 (開発部, 35歳, 600,000円)
部署→年齢順:
鈴木 (開発部, 25歳)
田中 (開発部, 28歳)
伊藤 (開発部, 35歳)
高橋 (営業部, 29歳)
佐藤 (営業部, 32歳)
部署→給与順(給与は高い順):
伊藤 (開発部, 600,000円)
田中 (開発部, 450,000円)
鈴木 (開発部, 380,000円)
佐藤 (営業部, 520,000円)
高橋 (営業部, 480,000円)
複数条件での並び替えも思った通りにできました。
実用的な活用例
sort()
メソッドを使った実際のプログラム例を見てみましょう。
これらの例を参考に、自分のプロジェクトでも活用してみてください。
成績処理システム
学生の成績を管理するシステムの例です。
class GradeProcessor: """成績処理クラス""" def __init__(self): self.students = [] def add_student(self, name, scores): """学生の成績を追加""" total = sum(scores) average = total / len(scores) if scores else 0 self.students.append({ "name": name, "scores": scores, "total": total, "average": average }) def sort_by_total(self, descending=True): """合計点でソート""" self.students.sort(key=lambda s: s["total"], reverse=descending) def sort_by_average(self, descending=True): """平均点でソート""" self.students.sort(key=lambda s: s["average"], reverse=descending) def sort_by_name(self): """名前でソート""" self.students.sort(key=lambda s: s["name"]) def print_ranking(self, sort_type="total"): """ランキングを表示""" if sort_type == "total": self.sort_by_total() key_name = "合計点" key_value = "total" elif sort_type == "average": self.sort_by_average() key_name = "平均点" key_value = "average" else: self.sort_by_name() key_name = "名前" key_value = "name" print(f"=== {key_name}順ランキング ===") for i, student in enumerate(self.students, 1): if key_value in ["total", "average"]: value = f"{student[key_value]:.1f}点" else: value = student[key_value] print(f"{i:2d}位: {student['name']} - {value}")
# 使用例processor = GradeProcessor()
# 学生データの追加processor.add_student("田中", [85, 90, 88])processor.add_student("佐藤", [92, 87, 91])processor.add_student("鈴木", [78, 83, 85])processor.add_student("高橋", [95, 89, 94])
# 各種ランキング表示processor.print_ranking("total")print()processor.print_ranking("average")
このコードでは、成績処理システムを作成しています。 様々な条件でランキングを表示できます。
実行結果:
=== 合計点順ランキング ===
1位: 高橋 - 278.0点
2位: 佐藤 - 270.0点
3位: 田中 - 263.0点
4位: 鈴木 - 246.0点
=== 平均点順ランキング ===
1位: 高橋 - 92.7点
2位: 佐藤 - 90.0点
3位: 田中 - 87.7点
4位: 鈴木 - 82.0点
成績管理が簡単にできました。
データ分析での並び替え
売上データの分析例を見てみましょう。
def analyze_sales_data(): """売上データの分析""" sales_data = [ {"product": "商品A", "price": 1000, "quantity": 150, "category": "電子機器"}, {"product": "商品B", "price": 1500, "quantity": 80, "category": "書籍"}, {"product": "商品C", "price": 800, "quantity": 200, "category": "食品"}, {"product": "商品D", "price": 2000, "quantity": 50, "category": "電子機器"}, {"product": "商品E", "price": 500, "quantity": 300, "category": "食品"} ] # 売上金額を計算 for item in sales_data: item["revenue"] = item["price"] * item["quantity"] print("=== 売上データ分析 ===") # 売上金額順(高い順) revenue_sorted = sales_data.copy() revenue_sorted.sort(key=lambda x: x["revenue"], reverse=True) print("売上金額順(高い順):") for item in revenue_sorted: print(f" {item['product']}: {item['revenue']:,}円") # 販売数量順(多い順) quantity_sorted = sales_data.copy() quantity_sorted.sort(key=lambda x: x["quantity"], reverse=True) print("販売数量順(多い順):") for item in quantity_sorted: print(f" {item['product']}: {item['quantity']}個") # カテゴリ→売上順 category_revenue_sorted = sales_data.copy() category_revenue_sorted.sort(key=lambda x: (x["category"], -x["revenue"])) print("カテゴリ→売上順:") current_category = None for item in category_revenue_sorted: if item["category"] != current_category: current_category = item["category"] print(f"[{current_category}]") print(f" {item['product']}: {item['revenue']:,}円")
analyze_sales_data()
このコードでは、売上データを様々な条件で分析しています。 ビジネスで使えそうな実用的な例ですね。
実行結果:
=== 売上データ分析 ===
売上金額順(高い順):
商品C: 160,000円
商品A: 150,000円
商品E: 150,000円
商品B: 120,000円
商品D: 100,000円
販売数量順(多い順):
商品E: 300個
商品C: 200個
商品A: 150個
商品B: 80個
商品D: 50個
カテゴリ→売上順:
[書籍]
商品B: 120,000円
[電子機器]
商品A: 150,000円
商品D: 100,000円
[食品]
商品C: 160,000円
商品E: 150,000円
様々な視点でデータを分析できました。
ソートの安定性
Pythonのsort()
メソッドは安定ソートという特性を持っています。
これは実用的にとても重要な特徴です。
安定ソートの確認
同じ値を持つ要素の順序が保たれることを確認してみましょう。
# 安定ソートのテストstudents = [ ("田中", 85), ("佐藤", 90), ("鈴木", 85), ("高橋", 90), ("伊藤", 85)]
print("元のデータ(入力順序):")for i, (name, score) in enumerate(students): print(f" {i+1}. {name}: {score}点")
# スコアでソート(安定ソート)students_by_score = students.copy()students_by_score.sort(key=lambda x: x[1])
print("スコア順ソート後:")for i, (name, score) in enumerate(students_by_score): print(f" {i+1}. {name}: {score}点")
print("同じスコアの学生の順序が保たれていることに注目")print("(85点:田中→鈴木→伊藤、90点:佐藤→高橋)")
このコードでは、同じスコアの学生の順序が元の順序を保っているかを確認しています。 これが安定ソートの特徴です。
実行結果:
元のデータ(入力順序):
1. 田中: 85点
2. 佐藤: 90点
3. 鈴木: 85点
4. 高橋: 90点
5. 伊藤: 85点
スコア順ソート後:
1. 田中: 85点
2. 鈴木: 85点
3. 伊藤: 85点
4. 佐藤: 90点
5. 高橋: 90点
同じスコアの学生の順序が保たれていることに注目
(85点:田中→鈴木→伊藤、90点:佐藤→高橋)
同じスコアの学生は元の順序が保たれています。
複数段階ソート
安定性を活用した複数段階ソートの例です。
def multi_stage_sort(): """複数段階でのソート""" employees = [ {"name": "田中", "dept": "開発", "level": 3, "salary": 450000}, {"name": "佐藤", "dept": "営業", "level": 2, "salary": 400000}, {"name": "鈴木", "dept": "開発", "level": 2, "salary": 380000}, {"name": "高橋", "dept": "営業", "level": 3, "salary": 480000}, {"name": "伊藤", "dept": "開発", "level": 3, "salary": 520000} ] print("元のデータ:") for emp in employees: print(f" {emp['name']} - {emp['dept']}部 (レベル{emp['level']}, {emp['salary']:,}円)") # 第1段階:給与でソート employees.sort(key=lambda x: x["salary"], reverse=True) print("第1段階:給与順(高い順)") for emp in employees: print(f" {emp['name']}: {emp['salary']:,}円") # 第2段階:部署でソート(給与順は保持される) employees.sort(key=lambda x: x["dept"]) print("第2段階:部署順(給与順は保持)") for emp in employees: print(f" {emp['name']} - {emp['dept']}部: {emp['salary']:,}円")
multi_stage_sort()
このコードでは、段階的にソートすることで複雑な並び替えを実現しています。 安定性により、前の段階の順序が保たれます。
実行結果:
元のデータ:
田中 - 開発部 (レベル3, 450,000円)
佐藤 - 営業部 (レベル2, 400,000円)
鈴木 - 開発部 (レベル2, 380,000円)
高橋 - 営業部 (レベル3, 480,000円)
伊藤 - 開発部 (レベル3, 520,000円)
第1段階:給与順(高い順)
伊藤: 520,000円
高橋: 480,000円
田中: 450,000円
佐藤: 400,000円
鈴木: 380,000円
第2段階:部署順(給与順は保持)
伊藤 - 開発部: 520,000円
田中 - 開発部: 450,000円
鈴木 - 開発部: 380,000円
高橋 - 営業部: 480,000円
佐藤 - 営業部: 400,000円
部署別にグループ化されつつ、給与順も保たれています。
まとめ
リストのsort()
メソッドは、Pythonでデータを効率的に並び替える最も基本的で重要な機能です。
この記事で学んだポイントを振り返ってみましょう。
sort()メソッドの特徴
主な特徴をまとめると以下のようになります。
- インプレース操作: 元のリストを直接変更
- 高速性: 内部的に最適化されたアルゴリズム(Timsort)
- 安定性: 同じキー値の要素の順序が保持される
- 柔軟性: key引数でカスタムソート条件を指定可能
主な使用場面
実際のプログラミングでは、こんな場面で活用できます。
- データ分析: 売上、スコア、統計データの順位付け
- ファイル管理: ファイル名、サイズ、日付での整理
- ユーザーインターフェース: 表示データの並び替え
- アルゴリズム: 検索や処理の効率化
ベストプラクティス
より良いプログラムを書くためのコツです。
- 適切な選択:
sort()
とsorted()
の使い分け - キー関数の最適化: 重い処理は事前計算
- 安定性の活用: 複数段階ソートの実現
- 結果の検証: 期待通りの結果かチェック
sort()
メソッドをマスターすることで、より効率的なデータ処理ができるようになります。
まずは基本的な数値や文字列の並び替えから始めて、徐々に複雑なソート条件にも挑戦してみてください。 データの整理がとても楽になりますよ!