5. リストと辞書でデータを整理
目次
- 5.1 リストとは?複数の値を順番に管理する方法
- 5.2 リストへの要素追加・削除・取り出し
- 5.3 辞書とは?「言葉(キー)」と「意味(値)」で管理
- 5.4 辞書への要素追加・更新・削除
- 5.5 リストと辞書を上手に使い分けよう
- 5.6 リスト内包表記でスマートにリストを作る
- 5.7 リストと辞書を組み合わせて複雑なデータを扱う
- Ex.1 クラス名簿(名前・点数)を辞書で管理して平均点を求めるプログラム
- Ex.2 好きな果物リストを作り、最初と最後の要素を表示するプログラム
この講座で使用する Google Colab の URL
5. リストと辞書でデータを整理 (Google Colab)
演習課題
Ex.5. リストと辞書でデータを整理 (Google Colab)
この講座で使用する Python, Jupyter Notebook のファイルと実行環境
Lesson 5: high-school-python-code (GitHub)
5.1 リストとは?複数の値を順番に管理する方法
学校の名簿、テストの各科目の点数など、私たちの周りには「データの一覧」がたくさんあります。Python では、このような複数のデータを順番に管理するために「リスト」という機能を使います。
リスト型 (list)
リストは配列(Array)とも呼ばれることがありますが、Python では list というデータ型です。
リストの作り方
基本的なリストの作成
fruits = ["りんご", "バナナ", "オレンジ"]
numbers = [1, 2, 3, 4, 5]
# 異なる型のデータも OK
mix = ["太郎", 15, "東京", 172.5]
# 空のリストを定義する
my_list = []
リストの要素を取り出す
リストの要素を指定するには、文字列と同じようにインデックスを使います。また、文字列で学んだのと同じように、スライスを使ったり、マイナスのインデックスを使ったりすることもできます。
リストの要素を取り出す
fruits = ["りんご", "バナナ", "オレンジ", "ぶどう", "メロン"]
# インデックスで要素を取り出す
print(fruits[0]) # りんご (最初の要素)
print(fruits[1]) # バナナ (2 番目の要素)
print(fruits[-1]) # メロン (最後の要素)
print(fruits[-2]) # ぶどう (後ろから 2 番目の要素)
# 範囲を指定して取り出す (スライス)
print(fruits[1:3]) # ['バナナ', 'オレンジ']
print(fruits[:3]) # ['りんご', 'バナナ', 'オレンジ']
print(fruits[2:]) # ['オレンジ', 'ぶどう', 'メロン']
リストの長さを調べる
また、len 関数を使ってリストの長さ(要素数)を調べることもできます。
リストの長さを調べる
fruits = ["りんご", "バナナ", "オレンジ"]
length = len(fruits)
print(f"リストの長さ:{length}") # 3
リストの型ヒント
リストにも型ヒントを書くことができます。リストの要素の型が決まっている場合は、型ヒントを書くことでコードを読みやすくすることができます。
リストの型ヒント
fruits: list[str] = ["りんご", "バナナ", "オレンジ"]
numbers: list[int] = [1, 2, 3, 4, 5]
この他にも色々な型ヒントの書き方がありますが(any, union など)、ここでは長くなるので省略します。
5.2 リストへの要素追加・削除・取り出し
リストは、一度作成した後でも内容を自由に変更することができます。要素の追加、削除、並び替えなど、色々な操作が可能です。
リストへの要素の追加
1. append(): 末尾に追加
append() は、リストの末尾に要素を追加するメソッドです。
append() で末尾に追加
foods = ["カレー", "ラーメン"]
foods.append("寿司")
print(foods) # ['カレー', 'ラーメン', '寿司']
# 複数回追加
foods.append("うどん")
foods.append("そば")
print(foods) # ['カレー', 'ラーメン', '寿司', 'うどん', 'そば']
2. insert(): 指定位置に追加
insert() は、指定した位置に要素を追加するメソッドです。
insert() で指定位置に追加
foods = ["カレー", "ラーメン", "寿司"]
# インデックス 1 の位置に挿入
foods.insert(1, "うどん")
print(foods) # ['カレー', 'うどん', 'ラーメン', '寿司']
# 先頭に追加
foods.insert(0, "そば")
print(foods) # ['そば', 'カレー', 'うどん', 'ラーメン', '寿司']
リストからの要素の削除
1. remove(): 指定した要素を削除
remove() は、指定した要素を削除するメソッドです。
remove() で指定した要素を削除
foods = ["カレー", "ラーメン", "寿司", "うどん"]
foods.remove("ラーメン")
print(foods) # ['カレー', '寿司', 'うどん']
# 存在しない要素を削除しようとするとエラーになります
foods.remove("パスタ")
2. del: インデックスを指定して削除
del は、指定したインデックスの要素を削除する演算子です。細かい話なのですが、メソッドではなく演算子です。
del でインデックスを指定して削除
foods = ["カレー", "ラーメン", "寿司", "うどん"]
# インデックス 1 の要素を削除
del foods[1]
print(foods) # ['カレー', '寿司', 'うどん']
# 範囲を指定して削除
# インデックス 1 から 2 までを削除
del foods[1:3]
print(foods) # ['カレー']
# 範囲外のインデックスを指定するとエラーになります
del foods[10]
3. pop(): 要素を取り出して削除
pop() は、指定した要素を取り出して削除するメソッドです。remove() や del とは違い、削除と同時に値を代入して使うことができます。
pop() で要素を取り出して削除
foods = ["カレー", "ラーメン", "寿司"]
last_food = foods.pop()
print(f"取り出した要素: {last_food}") # 寿司
print(f"残りのリスト: {foods}") # ['カレー', 'ラーメン']
# インデックスを指定して取り出し
second_food = foods.pop(1) # インデックス1の要素を取り出す
print(f"取り出した要素: {second_food}") # ラーメン
print(f"残りのリスト: {foods}") # ['カレー']
削除方法の使い分け
- remove(): 削除したい要素の値が分かっている時
- del: 削除したい位置が分かっている時
- pop(): 削除と同時に値を使いたい時
リストの操作と並び替え
1. sort(): 要素の並び替え
sort() は、リストの要素を並び替えるメソッドです。デフォルトでは昇順に並び替えられます。
Q: 昇順と降順の違いは?
A: 昇順は小さい順、降順は大きい順に並び替えます。昇順は小さい方から登っていくようなイメージ、降順は大きい方から下っていくようなイメージです。
sort() で要素の並び替え
# 数値のソート
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort() # 昇順に並び替え
print(numbers) # [1, 1, 2, 3, 4, 5, 9]
numbers.sort(reverse=True) # 降順に並び替え
print(numbers) # [9, 5, 4, 3, 2, 1, 1]
# 文字列のソート
names = ["Smith", "Brown", "Davis", "Anderson"]
names.sort() # アルファベット順に並び替え
print(names) # ['Anderson', 'Brown', 'Davis', 'Smith']
2. reverse(): 順序の反転
reverse() は、リストの順序を反転するメソッドです。
reverse() で順序を反転
foods = ["カレー", "ラーメン", "寿司"]
foods.reverse()
print(foods) # ['寿司', 'ラーメン', 'カレー']
3. count(): 要素の数を数える
count() は、指定した要素がリスト内に何回出現するかを数えるメソッドです。
count() で要素の数を数える
numbers = [1, 2, 3, 2, 1, 2, 4, 5]
count_2 = numbers.count(2)
print(f"2 の出現回数: {count_2}") # 3
# 文字列でも使える
fruits = ["りんご", "バナナ", "りんご", "オレンジ", "りんご"]
count_apple = fruits.count("りんご")
print(f"りんごの数: {count_apple}") # 3
Q: リストの操作でよくあるミスは?
A: 以下の点に注意しましょう:
- 存在しない要素の削除(remove)
- 範囲外のインデックスへのアクセス
- 異なる型のデータのソート
- 元のリストが変更されることの認識
5.3 辞書とは?「言葉(キー)」と「意味(値)」で管理
Python の「辞書(dictionary)」は、データを「キー(検索するための言葉)」と「値(対応する情報)」のペアで管理します。
実際の辞書でも、「単語」とその「意味」がセットになっています。
辞書 (Dictionary: dict)
辞書の作り方
このように辞書を作ることができます。
生徒の情報を辞書で管理
student = {
"name": "山田太郎", # キー: "name", 値: "山田太郎"
"age": 16, # キー: "age", 値: 16
"grade": 2, # キー: "grade", 値: 2
"class": "A" # キー: "class", 値: "A"
}
# 空の辞書を作る
my_dict = {}
値の取り出し方
辞書の値を取り出すには、キーを指定して取り出す方法と、get() メソッドを使う方法があります。
辞書の値を取り出す
student = {
"name": "山田太郎",
"age": 16,
"grade": 2,
"class": "A"
}
# [ ] を使って取り出す
print(student["name"]) # 山田太郎
print(student["age"]) # 16
# get() を使って安全に取り出す
print(student.get("name")) # 山田太郎
print(student.get("height")) # None (キーが存在しない場合)
print(student.get("height", 0)) # 0 (デフォルト値を指定)
dict[key] と dict.get() の違い
[key]
はキーが存在しないとエラーになるget(key)
はキーが存在しなくても安全 (None を返す)get(key, default)
は第 2 引数でデフォルト値を指定できる (例えば、なかったら 0 を返すなど)
2. キーと値の取得
辞書のキーと値を取得するには、keys() メソッドと values() メソッドを使います。
キーと値の取得
student = {
"name": "山田太郎",
"age": 16,
"grade": 2,
"class": "A"
}
# キーの一覧を取得
keys = student.keys()
print(list(keys)) # ['name', 'age', 'grade', 'class']
# 値の一覧を取得
values = student.values()
print(list(values)) # ['山田太郎', 16, 2, 'A']
# キーと値のペアを取得
items = student.items()
for key, value in items:
print(f"{key}: {value}")
Q: 辞書のキーには何を使える?
A: 以下のルールがあります:
- 変更不可能な型のみ使用可能(文字列、数値、タプルなど)
- リストは使用不可(変更可能なため)
- 同じキーは使用不可(一意である必要がある)
- キーは大文字小文字を区別する
なお、タプル (tuple) についてはレッスン 11 で扱います。
5.4 辞書への要素追加・更新・削除
辞書は、作成後でも要素の追加、更新、削除が自由にできます。ただし、操作によってはエラーになる可能性があるので、安全な操作方法を覚えておくことが大切です。
1. 追加・更新
値は、辞書を定義するタイミングで全て用意しておかなくても、後から追加したり、更新(変更)したりすることができます。
辞書の値の追加・更新
student = {"name": "山田太郎", "age": 16}
# 新しい要素の追加
student["grade"] = 2
student["class"] = "A"
print(student) # {'name': '山田太郎', 'age': 16, 'grade': 2, 'class': 'A'}
# 値の更新
student["age"] = 17
print(student) # {'name': '山田太郎', 'age': 17, 'grade': 2, 'class': 'A'}
複数の要素を一度に追加することもできます。
複数の要素を一度に追加
student = {"name": "山田太郎", "age": 16, "class": "A"}
student.update({"grade": 2, "club": "サッカー部"})
print(student)
2. 要素の削除
要素の削除は、del や pop(), clear() を使うことができます。違いを見ていきましょう。
del による削除
del による削除
student = {"name": "山田太郎", "age": 16, "grade": 2, "temp": "仮データ"}
# 特定の要素を削除
del student["temp"]
print(student) # temp キーが削除された辞書が表示される
pop による削除(値の取り出し)
pop による削除(値の取り出し)
# popで要素を削除しながら値を取得
student = {"name": "山田太郎", "age": 16, "grade": 2}
# 要素を削除して値を取得
age = student.pop("age")
print(f"取り出した年齢: {age}")
print(f"残りのデータ: {student}")
# 存在しないキーでもエラーにならない
club = student.pop("club", "未所属") # キーが存在しない場合のデフォルト値
print(f"部活動: {club}") # 未所属
clear() による全要素の削除
clear() による全要素の削除
scores = {"国語": 85, "数学": 92, "英語": 78}
print(f"クリア前: {scores}")
scores.clear() # すべての要素を削除
print(f"クリア後: {scores}") # {}
メソッドの使い分け: これらのようなメソッドを使い分けましょう。分からなくなったら調べながら使うと良いです。
get()
: 安全に値を取得(キーがなくてもエラーにならない)update()
: 複数の要素を一度に更新pop()
: 要素を削除しながら値を取得clear()
: すべての要素を削除
5.5 リストと辞書を上手に使い分けよう
プログラミングでは、状況に応じて適切なデータ構造を選ぶことが重要です。ここでは、リストと辞書のそれぞれの特徴を理解し、適切な使い分けをしましょう。
リストと辞書の比較
表の形で、リストと辞書の違いを見てみましょう。
リストの特徴 | 辞書の特徴 |
---|---|
順番に追加して保持される | キーと値のペアで管理 |
インデックス(0, 1, 2...)で要素にアクセス | キーで要素にアクセス |
同じ値を複数持てる | キーは一意(重複できない) |
※ Python のバージョン 3.7 以降では、辞書は追加された順番を保持します。
リストが適しているケース
1. 順番が重要な場合
ランキングや作り方の手順など、「順番通りに並んでいること」が重要なデータにはリストが適しています。
たとえばパンの作り方を手順ごとに保持し、上から順番に処理したいときなどです。
パンの作り方の手順
steps = ["材料を集める", "粉と水を混ぜる", "こねる", "発酵させる", "焼く"]
print("\nパンの作り方:")
for i, step in enumerate(steps, 1):
print(f"手順{i}: {step}")
2. 同じ種類のデータをまとめる場合
同じ種類のデータをまとめて管理したい時にはリストが適しています。
len 関数で要素の数を数えたり、sum 関数で合計を計算したりできます。
テストの点数リスト
test_scores: list[int] = [85, 92, 78, 90, 88]
# 基本的な統計計算
average = sum(test_scores) / len(test_scores)
highest = max(test_scores)
lowest = min(test_scores)
print(f"平均点: {average}")
print(f"最高点: {highest}")
print(f"最低点: {lowest}")
辞書が適しているケース
1. データに名前を付けて管理する場合
データに名前を付けて管理したい時には辞書が適しています。
これらはただ順番に並べているだけだと、何のデータなのか分かりにくくなってしまいます。
生徒の情報
student = {
"name": "鈴木花子",
"age": 16,
"grade": 2,
"class": "A",
"hobby": "バスケ",
"favorite_subject": "数学",
}
# 必要な情報だけを取り出せる
print(f"{student['name']}さん({student['grade']}-{student['class']})")
print(f"趣味: {student['hobby']}")
2. 素早い検索が必要な場合(多くの要素から探す場合)
リストで要素を探す場合は、最悪の場合、すべての要素を順番に確認する必要があります。
(アルゴリズムの分野では、この探し方は線形探索と呼ばれています)
一方、辞書はキーがわかっていれば高速にアクセスできます。
データ数が多く、「キーですばやく検索したい」シチュエーションなら、辞書の方が向いています。
電話帳
phone_book = {
"太郎": "090-1111-2222",
"花子": "080-3333-4444",
"次郎": "070-5555-6666",
}
# 名前 (キー) から電話番号の取得ができる
print(phone_book["太郎"])
5.6 リスト内包表記でスマートにリストを作る
リスト内包表記(List Comprehension)は、Python の強力な機能の 1 つです。for 文を使って書くコードを、より簡潔に書けます。
また、動作も通常の作り方よりも少しだけ速いです。
1. 基本的な形
リスト内包表記の基本的な形
# 通常の for 文での書き方
numbers = []
for i in range(1, 6):
numbers.append(i)
print(numbers) # [1, 2, 3, 4, 5]
# リスト内包表記での書き方
numbers = [i for i in range(1, 6)]
print(numbers) # [1, 2, 3, 4, 5]
2. 計算や処理を含む場合
計算を含む場合
計算を含むリスト内包表記
# 1 から 5 までの二乗のリスト
# 通常の for 文
squares = []
for i in range(1, 6):
squares.append(i**2)
print(squares) # [1, 4, 9, 16, 25]
# リスト内包表記
squares = [i**2 for i in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]
文字列の処理を含む場合
文字列の処理を含むリスト内包表記
# 文字列の各文字を大文字にする
word = "Python"
# 通常の for 文
upper_chars = []
for char in word:
upper_chars.append(char.upper())
print(upper_chars) # ['P', 'Y', 'T', 'H', 'O', 'N']
# リスト内包表記
upper_chars = [char.upper() for char in word]
print(upper_chars) # ['P', 'Y', 'T', 'H', 'O', 'N']
3. if 条件を使った形
if を使って、条件に一致するものだけをリストに含めることもできます。
for と if の順番に注意してください。
if 条件を使ったリスト内包表記
# 10 以下の偶数をリストにする
# 通常の for 文
evens = []
for i in range(11):
if i % 2 == 0:
evens.append(i)
print(evens) # [0, 2, 4, 6, 8, 10]
# リスト内包表記
evens = [i for i in range(11) if i % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10]
リスト内包表記は、二重、三重に使うこともできます。ただ、あまり使いすぎるとコードが読みにくくなってしまうので、バランスを考えて使うと良いです。
複雑で読みにくいリスト内包表記
# 複雑で読みにくい (かもしれない)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [x for row in matrix for x in row if x % 2 == 0]
# 普通に for 文で書く場合
flattened = []
for row in matrix:
for x in row:
if x % 2 == 0:
flattened.append(x)
辞書内包表記で効率的に辞書を作る
リスト内包表記と同様に、Python では辞書内包表記(Dictionary Comprehension)を使って、簡潔に辞書を作成することができます。
ここでは、2つの例を見てみましょう。
1. 基本的な形
辞書内包表記の基本的な形
# 通常の for 文での書き方
squares_dict = {}
for i in range(1, 6):
squares_dict[i] = i**2
print(squares_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 辞書内包表記での書き方
squares_dict = {i: i**2 for i in range(1, 6)}
print(squares_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
2. if 条件を使った形
リスト内包表記と同様に、if 条件を使って特定の要素だけを含める辞書を作成できます。
また、ここでは、items() メソッドを使って、辞書のキーと値を同時に取得しています。
if 条件を使った辞書内包表記
# 値が 10 以上の要素だけを含める
scores = {'Alice': 12, 'Bob': 8, 'Charlie': 15, 'David': 9}
# 通常の for 文
high_scores = {}
for name, score in scores.items():
if score >= 10:
high_scores[name] = score
print(high_scores) # {'Alice': 12, 'Charlie': 15}
# 辞書内包表記
high_scores = {name: score for name, score in scores.items() if score >= 10}
print(high_scores) # {'Alice': 12, 'Charlie': 15}
辞書内包表記も、リスト内包表記と同様に、複雑になりすぎないように注意が必要です。読みやすさを保つために、必要以上に複雑な処理は通常の for 文で書くことをお勧めします。
5.7 リストと辞書を組み合わせて複雑なデータを扱う
実際のプログラムでは、より複雑なデータを扱うことが多くあります。
そんな時、リストと辞書を組み合わせることで、柔軟なデータ構造を作ることができます。
基本的な組み合わせ方
1. リストの中に辞書を入れる
生徒の辞書リスト
students = [
{"name": "山田太郎", "age": 16, "class": "A"},
{"name": "鈴木花子", "age": 15, "class": "B"},
{"name": "佐藤次郎", "age": 17, "class": "C"},
]
# データの表示
for student in students:
print(f"{student['name']} ({student['age']}歳) - {student['class']}組")
2. 辞書の中にリストを入れる
各教科の試験結果
# 4 人分の試験結果
test_results = {
"数学": [85, 92, 78, 90],
"英語": [92, 88, 85, 95],
"国語": [88, 90, 85, 82],
}
# 教科ごとの平均点を計算
for subject, scores in test_results.items():
average = sum(scores) / len(scores)
# 平均点を小数第 1 位まで表示
print(f"{subject}の平均点: {average:.1f}")
もっと複雑な使い方
辞書の中に、さらに辞書を入れることもできます。
実際のデータは、このように複雑になっていることも多いので、上手くデータ構造を組み合わせて行くことが大切です。
クラスごとの成績管理
classes_data = {
"A組": [
{"name": "山田太郎", "scores": {"数学": 85, "英語": 92, "国語": 88}},
{"name": "鈴木花子", "scores": {"数学": 92, "英語": 88, "国語": 90}},
],
"B組": [
{"name": "佐藤次郎", "scores": {"数学": 78, "英語": 85, "国語": 85}},
{"name": "田中明", "scores": {"数学": 90, "英語": 95, "国語": 82}},
],
}
# クラスごとの成績表示
for class_name, students in classes_data.items():
print(f"{class_name}の成績:")
for student in students:
print(f"{student['name']}の成績:")
for subject, score in student["scores"].items():
print(f" {subject}: {score}点")
print()
Ex.1 クラス名簿(名前・点数)を辞書で管理して平均点を求めるプログラム
クラスの成績管理プログラム
class_scores = {
"山田太郎": 85,
"鈴木花子": 92,
"佐藤次郎": 78,
"田中美咲": 95,
"高橋健一": 88,
}
# 平均点を計算
total = sum(class_scores.values())
average = total / len(class_scores)
# 平均点を小数第 1 位まで表示
print(f"クラスの平均点:{average:.1f}")
# 平均点以上の生徒を表示
print("\n平均点以上の生徒:")
for name, score in class_scores.items():
if score >= average:
print(f"{name}: {score}点")
チャレンジ:
- 最高点と最低点の生徒を表示してみよう
- 点数帯(90 点以上、80 - 89 点、...)ごとの人数を集計してみよう
- 複数の科目の点数を管理してみよう
Ex.2 好きな果物リストを作り、最初と最後の要素を表示するプログラム
好きな果物リストを作り、最初と最後の要素を表示するプログラム
# 果物リストを作成
fruits = []
# 果物を追加
while True:
fruit = input("好きな果物を入力してください(終了する場合は quit と入力してください):")
if fruit == "quit":
break
fruits.append(fruit)
# リストが空でない場合のみ表示
if fruits:
print("\n入力された果物リスト:")
print(fruits)
print(f"最初の果物:{fruits[0]}")
print(f"最後の果物:{fruits[-1]}")
print(f"果物の総数:{len(fruits)}個")
else:
print("果物が入力されませんでした")
チャレンジ:
- 果物を五十音順に並び替えてみよう
- 重複する果物を除外してみよう
- 果物とその好きな度合い(5 段階)も記録してみよう
まとめ
この章で学んだこと:
- リストは順序付きのデータ集合
- 辞書はキーと値のペアでデータを管理
- リストと辞書を組み合わせて、柔軟にデータ構造を作る
- 内包表記で簡潔にリストや辞書を作成する