5. リストと辞書でデータを整理

目次

この講座で使用する 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}")  # ['カレー']

リストの操作と並び替え

1. sort(): 要素の並び替え

sort() は、リストの要素を並び替えるメソッドです。デフォルトでは昇順に並び替えられます。

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

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 (デフォルト値を指定)

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}")

なお、タプル (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}")  # {}

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}

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 段階)も記録してみよう

まとめ

この章で学んだこと:

  • リストは順序付きのデータ集合
  • 辞書はキーと値のペアでデータを管理
  • リストと辞書を組み合わせて、柔軟にデータ構造を作る
  • 内包表記で簡潔にリストや辞書を作成する