Pythonのデータ構造:リスト、タプル、辞書、集合
2025-10-23はじめに
前回の講義では関数の定義と呼び出しについて学びました。今回は、Pythonでデータを効率的に管理・操作するための4つの重要なデータ構造「リスト、タプル、辞書、集合」について詳しく学びます。これらのデータ構造は、現実世界の様々なデータを表現するために不可欠なツールです。
データ構造の重要性
データ構造は、データを効率的に整理、保存、操作する方法を提供します。適切なデータ構造を選択することで以下のメリットがあります。
- コードの可読性が向上する
- 処理速度が速くなる
- メモリ使用量が最適化される
- データの操作が容易になる
データ構造のそれぞれを詳細に説明していきます。
リスト(List)
リストの基本
リストは、複数の要素を順序付けて格納できるデータ型です。異なるデータ型の要素を混在でき、要素の追加・変更・削除が可能な可変性を持ちます。角括弧[]で作成し、カンマ区切りで要素を並べます。データの整理や繰り返し処理に広く利用されます。
# リストの作成
fruits = ["apple", "banana", "orange", "grape"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
print(f"フルーツリスト: {fruits}")
print(f"数値リスト: {numbers}")
print(f"混合リスト: {mixed}")
リストの操作
インデックス指定による要素へのアクセス、スライスによる部分リストの取得、要素の変更、append()やinsert()を使った追加、pop()やremove()、delを用いた削除など、リストの基本的な操作を網羅しています。実行結果をコメントで示すことで、各操作がリストにどのような影響を与えるかを明確に理解できるようになっています。
# 要素のアクセスと変更
fruits = ["apple", "banana", "orange", "grape"]
print(f"最初の要素: {fruits[0]}") # apple
print(f"最後の要素: {fruits[-1]}") # grape
print(f"スライス: {fruits[1:3]}") # ['banana', 'orange']
# 要素の変更
fruits[1] = "mango"
print(f"変更後: {fruits}") # ['apple', 'mango', 'orange', 'grape']
# 要素の追加
fruits.append("peach") # 末尾に追加
fruits.insert(1, "kiwi") # 指定位置に追加
print(f"追加後: {fruits}")
# 要素の削除
removed = fruits.pop() # 末尾を削除
print(f"削除された要素: {removed}")
fruits.remove("orange") # 特定の要素を削除
del fruits[0] # インデックス指定で削除
print(f"削除後: {fruits}")
リストのメソッド
リストの長さや要素の出現回数を調べる基本的なメソッド、ソートや反転による並び替え、リストの結合方法を扱っています。さらに、簡潔な記述でリストを生成できるリスト内包表記も紹介しており、条件付きで偶数の平方数を求める応用的な使用例も含まれています。これらの操作を通して、リストの効率的な扱い方を学ぶことができます。
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# 基本的なメソッド
print(f"リストの長さ: {len(numbers)}")
print(f"要素1の出現回数: {numbers.count(1)}")
print(f"要素9のインデックス: {numbers.index(9)}")
# ソート
numbers.sort()
print(f"昇順ソート: {numbers}")
numbers.sort(reverse=True)
print(f"降順ソート: {numbers}")
# 反転
numbers.reverse()
print(f"反転: {numbers}")
# リストの結合
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2
print(f"結合: {combined}")
# リスト内包表記
squares = [x**2 for x in range(1, 6)]
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(f"平方数: {squares}")
print(f"偶数の平方数: {even_squares}")
タプル(Tuple)
タプルの基本
タプルはリストと似ていますが、一度作成すると要素の変更・追加・削除ができない不変性(immutable)が特徴です。丸括弧()で作成し、要素の順序を保持します。データの改変を防ぎたい場合や、辞書のキーとして使用する場合などに利用されます。
# タプルの作成
colors = ("red", "green", "blue")
coordinates = (10, 20)
single_element = (42,) # 要素が1つの場合はカンマが必要
mixed_tuple = (1, "hello", 3.14)
print(f"色のタプル: {colors}")
print(f"座標: {coordinates}")
print(f"単一要素: {single_element}")
# 要素のアクセス(リストと同じ)
print(f"最初の色: {colors[0]}")
print(f"最後の色: {colors[-1]}")
print(f"スライス: {colors[1:]}")
# タプルは不変なので以下の操作はエラー
# colors[0] = "yellow" # TypeError
タプルの利点と使用場面
関数の戻り値として複数の値をまとめて返す方法、変更不可能な特性を活かして辞書のキーとして使用する方法、データの不変性を利用して設定値など誤った変更を防ぎたい情報を保護する方法を実演しています。タプルの特徴である不変性が、それぞれの場面でどのように役立つかを具体的に理解できます。
# 関数の戻り値として(複数の値を返す)
def get_user_info():
return "Alice", 25, "Tokyo"
name, age, city = get_user_info()
print(f"名前: {name}, 年齢: {age}, 都市: {city}")
# 辞書のキーとして(リストは不可)
locations = {
(35.6895, 139.6917): "Tokyo",
(40.7128, -74.0060): "New York"
}
print(f"東京の座標: {locations[(35.6895, 139.6917)]}")
# データの保護(誤って変更されるのを防ぐ)
config = ("localhost", 8080, "production")
print(f"設定: {config}")
辞書(Dictionary)
辞書の基本
ディクショナリーはキーと値のペアを格納するコレクションです。波括弧{}で囲み、キーと値をコロン「:」で結んで定義します。キーを通じて対応する値に高速にアクセスでき、要素の追加・変更・削除が可能です。リストとは異なり、要素の順序は保証されませんが、キーによる直接アクセスという特性から、データベース的な役割を果たします。
# 辞書の作成
student = {
"name": "Alice",
"age": 20,
"major": "Computer Science",
"grades": [85, 92, 78]
}
person = dict(name="Bob", age=25, city="New York")
print(f"学生情報: {student}")
print(f"人物情報: {person}")
# 要素のアクセス
print(f"名前: {student['name']}")
print(f"年齢: {student.get('age')}")
print(f"存在しないキー: {student.get('height', '不明')}")
# 要素の追加と更新
student["email"] = "alice@example.com" # 追加
student["age"] = 21 # 更新
print(f"更新後: {student}")
# 要素の削除
removed_grade = student.pop("grades") # キー指定で削除
print(f"削除された成績: {removed_grade}")
del student["major"] # del文で削除
print(f"削除後: {student}")
辞書の操作
keys()、values()、items()メソッドによる辞書内容の取得方法、キーまたは項目を用いた効率的なループ処理、簡潔な記法で辞書を生成する内包表記、そして複数の辞書を結合する方法を実演しています。各操作を通じて、辞書の柔軟なデータ管理能力と、キーと値のペアを効果的に扱う手法を理解することができます。
# 辞書のメソッド
student = {"name": "Alice", "age": 20, "major": "CS"}
print(f"すべてのキー: {list(student.keys())}")
print(f"すべての値: {list(student.values())}")
print(f"すべての項目: {list(student.items())}")
# ループ処理
print("\nキーでループ:")
for key in student:
print(f" {key}: {student[key]}")
print("\n項目でループ:")
for key, value in student.items():
print(f" {key}: {value}")
# 辞書内包表記
numbers = [1, 2, 3, 4, 5]
squares_dict = {x: x**2 for x in numbers}
print(f"平方辞書: {squares_dict}")
# 辞書の結合
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
combined = {**dict1, **dict2}
print(f"結合後: {combined}")
集合(Set)
集合の基本
セットは重複しない要素の順序なしコレクションを格納します。波括弧{}で作成し、数学の集合演算(和集合、積集合、差集合など)をサポートします。要素の追加・削除が可能ですが、変更不可能なオブジェクトのみを要素とし、リストや辞書などは含めません。データの重複排除や集合演算が必要な場面で威力を発揮します。
# 集合の作成
fruits = {"apple", "banana", "orange", "apple"} # 重複は自動除去
numbers = set([1, 2, 3, 4, 5, 5, 5]) # リストから変換
empty_set = set() # 空集合
print(f"フルーツ集合: {fruits}") # {'banana', 'orange', 'apple'}
print(f"数値集合: {numbers}") # {1, 2, 3, 4, 5}
print(f"空集合: {empty_set}")
# 要素の追加と削除
fruits.add("grape")
fruits.add("banana") # 重複なので無視
fruits.remove("apple")
# fruits.remove("melon") # 存在しない要素はKeyError
fruits.discard("melon") # 安全な削除(エラーなし)
print(f"更新後: {fruits}")
集合演算
和集合・積集合・差集合・対称差集合といった基本的な集合演算を演算子を用いて実行し、部分集合や上位集合の関係性を確認する方法を実演しています。各演算結果から、集合がデータの比較やフィルタリング、数学的集合操作にどのように活用できるかを具体的に理解することができます。
set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7, 8}
# 和集合(union)
union = set_a | set_b
print(f"和集合: {union}") # {1, 2, 3, 4, 5, 6, 7, 8}
# 積集合(intersection)
intersection = set_a & set_b
print(f"積集合: {intersection}") # {4, 5}
# 差集合(difference)
difference = set_a - set_b
print(f"差集合 A-B: {difference}") # {1, 2, 3}
# 対称差集合(symmetric difference)
symmetric_diff = set_a ^ set_b
print(f"対称差: {symmetric_diff}") # {1, 2, 3, 6, 7, 8}
# 部分集合・上位集合
print(f"AはBの部分集合: {set_a <= set_b}") # False
print(f"AはBの真部分集合: {set_a < set_b}") # False
print(f"{{4,5}}はAの部分集合: {{4, 5}} <= set_a") # True
データ構造の比較
ここまで説明した4つのデータ構造を比較します。
特性の比較
| 特徴 | リスト | タプル | 辞書 | 集合 |
|---|---|---|---|---|
| 変更可能 | ✅ | ❌ | ✅ | ✅ |
| 順序保持 | ✅ | ✅ | ✅ | ❌ |
| 重複許可 | ✅ | ✅ | ❌ | ❌ |
| インデックスアクセス | ✅ | ✅ | ✅(キーで) | ❌ |
| 使用例 | データシーケンス | 固定データ | キーバリューペア | 一意な要素 |
パフォーマンス比較
リストと集合におけるメンバーシップテスト(要素の存在確認)の性能差を実証しています。100万個の要素に対して特定の値が含まれるかをチェックする時間を計測し、リストが線形探索(O(n))であるのに対し、集合はハッシュベースの探索(O(1))であるため、はるかに高速であることを明確に示しています。大規模データにおける効率的な検索手法として集合の優位性がわかります。
import time
# リスト vs 集合(メンバーシップテスト)
large_list = list(range(1000000))
large_set = set(range(1000000))
# リストのメンバーシップテスト
start = time.time()
999999 in large_list
end = time.time()
print(f"リストのメンバーシップテスト: {end - start:.6f}秒")
# 集合のメンバーシップテスト
start = time.time()
999999 in large_set
end = time.time()
print(f"集合のメンバーシップテスト: {end - start:.6f}秒")
実践的な使用例
データ分析の例
辞書とリストを組み合わせた実践的な学生成績管理システムです。各学生の情報を辞書で表現し、それらをリストで管理しています。平均点の計算、専攻ごとの学生のグループ化を行い、データの集計と整理方法を示しています。ループ処理と辞書操作を活用することで、現実的なデータ処理タスクを効率的に実行する方法を実証しています。
# 学生の成績管理システム
students = [
{"name": "Alice", "grades": [85, 92, 78], "major": "CS"},
{"name": "Bob", "grades": [76, 88, 95], "major": "Math"},
{"name": "Charlie", "grades": [90, 85, 92], "major": "CS"},
{"name": "Diana", "grades": [65, 70, 75], "major": "Physics"}
]
# 各学生の平均点を計算
for student in students:
grades = student["grades"]
average = sum(grades) / len(grades)
student["average"] = round(average, 2)
# 専攻ごとの学生をグループ化
majors = {}
for student in students:
major = student["major"]
if major not in majors:
majors[major] = []
majors[major].append(student)
# 結果の表示
print("学生の成績:")
for student in students:
print(f"{student['name']}: 平均 {student['average']}点")
print("\n専攻別学生:")
for major, students_in_major in majors.items():
names = [s["name"] for s in students_in_major]
print(f"{major}: {', '.join(names)}")
テキスト処理の例
テキスト分析を行う実践的な関数を実装しています。文字列操作、辞書、集合を組み合わせて、総単語数、ユニーク単語数、単語の出現頻度、最も頻出する単語トップ5を計算します。具体的には、テキストを単語に分割し、辞書で頻度を集計し、集合でユニーク単語を管理することで、効率的なテキスト分析の手法を示しています。実際のデータ処理でよく使われる技術を網羅した例です。
def analyze_text(text):
"""テキストを分析する関数"""
# 単語のリストを作成
words = text.lower().split()
# 単語の頻度を計算
word_freq = {}
for word in words:
# 句読点を除去
word = word.strip('.,!?;:"')
if word:
word_freq[word] = word_freq.get(word, 0) + 1
# ユニークな単語の集合
unique_words = set(words)
# 結果を返す
return {
"total_words": len(words),
"unique_words": len(unique_words),
"word_frequency": word_freq,
"most_common": sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:5]
}
# 使用例
sample_text = """
Python is a powerful programming language. Python is easy to learn and use.
Python has many libraries for data analysis. Python is popular for web development.
"""
analysis = analyze_text(sample_text)
print(f"総単語数: {analysis['total_words']}")
print(f"ユニーク単語数: {analysis['unique_words']}")
print(f"最も頻出する単語: {analysis['most_common']}")
設定管理の例
変更不可なシステム設定にはタプルを、ユーザー設定には柔軟な辞書を使用し、関数でこれらを統合しています。タプルの不変性による設定の保護、辞書の柔軟性によるユーザーカスタマイズ、集合を用いた機能管理など、各データ型の特性を活かした設計が特徴です。現実的なアプリケーション設定のモデルとして参考になります。
# アプリケーションの設定
DEFAULT_CONFIG = (
"localhost", # host
8080, # port
True, # debug_mode
"production", # environment
)
# ユーザー設定(辞書)
user_settings = {
"theme": "dark",
"language": "ja",
"notifications": True,
"font_size": 14,
"shortcuts": {"save": "Ctrl+S", "undo": "Ctrl+Z"}
}
# システム設定(変更不可なタプル)
SYSTEM_SETTINGS = (
"1.0.0", # version
"UTF-8", # encoding
1000, # max_connections
)
def create_app_config(host, port, user_preferences):
"""アプリケーション設定を作成"""
config = {
"connection": (host, port),
"system": SYSTEM_SETTINGS,
"user": user_preferences,
"features": {"api", "database", "cache"} # 利用可能な機能
}
return config
# 設定の作成と使用
app_config = create_app_config("127.0.0.1", 3000, user_settings)
print("アプリケーション設定:")
for key, value in app_config.items():
print(f" {key}: {value}")
どのデータ構造を使うべきか?
- リスト: 順序が重要で、重複を許可し、変更可能なシーケンス
- 例: タスクリスト、履歴、測定値のシーケンス
- タプル: 順序が重要で、変更しないことが保証されているシーケンス
- 例: 座標、データベースのレコード、関数の戻り値
- 辞書: キーによる高速な検索が必要なキーバリューペア
- 例: 設定、データベースのレコード、キャッシュ
- 集合: 一意性が重要で、集合演算が必要な場合
- 例: タグ、カテゴリ、ユニークなユーザーID
メモリとパフォーマンスの考慮
データ構造におけるメモリ使用量を比較検証しています。同じ要素数(5つの整数)を持つリスト、タプル、集合、辞書のメモリ消費量をsys.getsizeof()関数で測定し、各データ型のメモリ効率の違いを数値的に示しています。データ構造の選択がメモリ使用量に与える影響を理解するための実践的な計測例となっています。
import sys
# メモリ使用量の比較
list_data = [1, 2, 3, 4, 5]
tuple_data = (1, 2, 3, 4, 5)
set_data = {1, 2, 3, 4, 5}
dict_data = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}
print(f"リストのメモリ使用量: {sys.getsizeof(list_data)} bytes")
print(f"タプルのメモリ使用量: {sys.getsizeof(tuple_data)} bytes")
print(f"集合のメモリ使用量: {sys.getsizeof(set_data)} bytes")
print(f"辞書のメモリ使用量: {sys.getsizeof(dict_data)} bytes")
まとめ
この講義では、Pythonの4つの主要なデータ構造について学びました:
- リスト: 順序付けられた可変シーケンス
- タプル: 順序付けられた不変シーケンス
- 辞書: キーと値のペアのコレクション
- 集合: 重複しない要素の無順序コレクション
主要なポイント:
- 各データ構造には特定の用途と利点がある
- 適切なデータ構造の選択はパフォーマンスに大きく影響する
- リスト内包表記や辞書内包表記を使うとコードが簡潔になる
- データ構造を組み合わせて複雑なデータを表現できる
これらのデータ構造を適切に使い分けることで、効率的で読みやすいコードを書くことができます。次の講義では、ファイル操作について学び、データの永続化について理解を深めます。
練習問題
初級問題(3問)
問題1
1から10までの数値を含むリストを作成し、以下の操作を行うプログラムを作成してください。
- リストの内容を表示
- リストの長さを表示
- リストの最後に11を追加
- リストの先頭を削除
- 最終的なリストを表示
問題2
以下のタプルから要素を取り出して、フォーマットされた文字列を作成してください。
person = ("山田", "太郎", 25, "東京")
結果: "山田太郎さんは25歳で東京に住んでいます"
問題3
以下の辞書を作成し、すべてのキー、すべての値、すべてのキーと値のペアを表示してください。
student = {
"name": "Alice",
"age": 20,
"major": "Computer Science",
"gpa": 3.8
}
中級問題(6問)
問題4
数値のリストを受け取り、以下の統計情報を計算する関数を作成してください。
- 平均値
- 最大値
- 最小値
- 合計値
関数は辞書形式でこれらの値を返してください。
問題5
2つのリストを受け取り、それらの共通要素を見つけて集合として返す関数を作成してください。
問題6
文章を受け取り、単語の頻度を辞書で返す関数を作成してください。大文字小文字を区別せず、句読点は無視してください。
問題7
学生の成績データを管理するプログラムを作成してください。
- 各学生は名前と複数の科目の点数を持つ
- 平均点を計算
- 最高点と最低点を見つける
- 成績順にソートして表示
問題8
リスト内包表記を使用して、以下のリストを作成してください。
- 1から20までの偶数のリスト
- 1から10までの数の平方根のリスト(小数第2位まで)
- 与えられた文字列リストから、長さが5文字以上の文字列だけを抽出したリスト
問題9
2つの辞書を結合する関数を作成してください。同じキーがある場合は、第2の辞書の値で上書きしてください。
上級問題(3問)
問題10
行列の加算と乗算を行う関数を作成してください。行列は2次元リストで表現します。エラーハンドリング(次元の一致チェックなど)も実装してください。
問題11
ショッピングカートシステムを辞書とリストを使用して作成してください。
- 商品の追加・削除
- 数量の変更
- 合計金額の計算
- カートの内容表示
問題12
データの分析プログラムを作成してください。以下の機能を含めてください。
- 複数の学生のデータ(名前、科目、点数)を受け取る
- 各科目の平均点・最高点・最低点を計算
- 学生ごとの平均点を計算
- 成績順位を表示
- 科目ごとの成績分布を表示
リスト、タプル、辞書、集合 練習問題 解答
初級問題 解答
問題1 解答
# 1から10までの数値リストを作成
numbers = list(range(1, 11))
print(f"元のリスト: {numbers}")
# リストの長さを表示
print(f"リストの長さ: {len(numbers)}")
# リストの最後に11を追加
numbers.append(11)
print(f"11を追加後: {numbers}")
# リストの先頭を削除
removed_element = numbers.pop(0)
print(f"削除された要素: {removed_element}")
print(f"先頭削除後: {numbers}")
# 最終的なリストを表示
print(f"最終的なリスト: {numbers}")
print(f"最終的な長さ: {len(numbers)}")
# 追加の操作例
print("\n追加の操作例:")
# 特定の位置に要素を挿入
numbers.insert(2, 99)
print(f"位置2に99を挿入: {numbers}")
# 要素の出現回数をカウント
numbers.extend([5, 5, 5])
print(f"5を3回追加: {numbers}")
print(f"5の出現回数: {numbers.count(5)}")
# リストの反転
numbers.reverse()
print(f"反転後: {numbers}")
実行結果:
元のリスト: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
リストの長さ: 10
11を追加後: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
削除された要素: 1
先頭削除後: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
最終的なリスト: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
最終的な長さ: 10
追加の操作例:
位置2に99を挿入: [2, 3, 99, 4, 5, 6, 7, 8, 9, 10, 11]
5を3回追加: [2, 3, 99, 4, 5, 6, 7, 8, 9, 10, 11, 5, 5, 5]
5の出現回数: 4
反転後: [5, 5, 5, 11, 10, 9, 8, 7, 6, 5, 4, 99, 3, 2]
問題2 解答
# タプルから要素を取り出して文字列を作成
person = ("山田", "太郎", 25, "東京")
# 方法1: インデックスでアクセス
introduction1 = f"{person[0]}{person[1]}さんは{person[2]}歳で{person[3]}に住んでいます"
print(f"方法1: {introduction1}")
# 方法2: アンパックして変数に代入
last_name, first_name, age, city = person
introduction2 = f"{last_name}{first_name}さんは{age}歳で{city}に住んでいます"
print(f"方法2: {introduction2}")
# 方法3: フォーマットメソッドを使用
introduction3 = "{}{}さんは{}歳で{}に住んでいます".format(*person)
print(f"方法3: {introduction3}")
# 複数のタプルを処理する例
people = [
("佐藤", "花子", 30, "大阪"),
("鈴木", "一郎", 22, "名古屋"),
("田中", "美咲", 28, "福岡")
]
print("\n複数の人物紹介:")
for i, (last_name, first_name, age, city) in enumerate(people, 1):
intro = f"{last_name}{first_name}さんは{age}歳で{city}に住んでいます"
print(f"{i}. {intro}")
# タプルの部分的なアンパック
print("\n部分的なアンパック:")
first_person = people[0]
name_part, *rest = first_person
print(f"名前部分: {name_part}")
print(f"その他: {rest}")
実行結果:
方法1: 山田太郎さんは25歳で東京に住んでいます
方法2: 山田太郎さんは25歳で東京に住んでいます
方法3: 山田太郎さんは25歳で東京に住んでいます
複数の人物紹介:
1. 佐藤花子さんは30歳で大阪に住んでいます
2. 鈴木一郎さんは22歳で名古屋に住んでいます
3. 田中美咲さんは28歳で福岡に住んでいます
部分的なアンパック:
名前部分: 佐藤
その他: ['花子', 30, '大阪']
問題3 解答
# 学生情報の辞書
student = {
"name": "Alice",
"age": 20,
"major": "Computer Science",
"gpa": 3.8
}
print("学生情報:")
print(f"辞書全体: {student}")
# すべてのキーを表示
print("\nすべてのキー:")
keys = student.keys()
print(f"keys(): {keys}")
print(f"リスト形式: {list(keys)}")
# すべての値を表示
print("\nすべての値:")
values = student.values()
print(f"values(): {values}")
print(f"リスト形式: {list(values)}")
# すべてのキーと値のペアを表示
print("\nすべてのキーと値のペア:")
items = student.items()
print(f"items(): {items}")
print(f"リスト形式: {list(items)}")
# ループを使用した詳細な表示
print("\n詳細な表示:")
print("キーのみ:")
for key in student:
print(f" - {key}")
print("\n値のみ:")
for value in student.values():
print(f" - {value}")
print("\nキーと値のペア:")
for key, value in student.items():
print(f" - {key}: {value}")
# 辞書のメソッドを使った実用的な例
print("\n実用的な使用例:")
# キーの存在チェック
if "name" in student:
print(f"名前: {student['name']}")
# getメソッドで安全にアクセス
phone = student.get("phone", "未登録")
print(f"電話番号: {phone}")
# 辞書の更新
student.update({"age": 21, "phone": "123-4567"})
print(f"更新後: {student}")
実行結果:
学生情報:
辞書全体: {'name': 'Alice', 'age': 20, 'major': 'Computer Science', 'gpa': 3.8}
すべてのキー:
keys(): dict_keys(['name', 'age', 'major', 'gpa'])
リスト形式: ['name', 'age', 'major', 'gpa']
すべての値:
values(): dict_values(['Alice', 20, 'Computer Science', 3.8])
リスト形式: ['Alice', 20, 'Computer Science', 3.8]
すべてのキーと値のペア:
items(): dict_items([('name', 'Alice'), ('age', 20), ('major', 'Computer Science'), ('gpa', 3.8)])
リスト形式: [('name', 'Alice'), ('age', 20), ('major', 'Computer Science'), ('gpa', 3.8)]
詳細な表示:
キーのみ:
- name
- age
- major
- gpa
値のみ:
- Alice
- 20
- Computer Science
- 3.8
キーと値のペア:
- name: Alice
- age: 20
- major: Computer Science
- gpa: 3.8
実用的な使用例:
名前: Alice
電話番号: 未登録
更新後: {'name': 'Alice', 'age': 21, 'major': 'Computer Science', 'gpa': 3.8, 'phone': '123-4567'}
中級問題 解答
問題4 解答
def calculate_statistics(numbers):
"""
数値のリストから統計情報を計算する
Parameters:
numbers (list): 数値のリスト
Returns:
dict: 統計情報を含む辞書
"""
if not numbers:
return {
"average": 0,
"max": 0,
"min": 0,
"sum": 0,
"count": 0
}
total = sum(numbers)
count = len(numbers)
average = total / count
maximum = max(numbers)
minimum = min(numbers)
return {
"average": round(average, 2),
"max": maximum,
"min": minimum,
"sum": total,
"count": count
}
# 関数のテスト
test_cases = [
[1, 2, 3, 4, 5],
[10, 20, 30, 40, 50],
[2.5, 3.7, 1.8, 4.2, 5.1],
[-5, -2, 0, 3, 7],
[], # 空リスト
[42] # 単一要素
]
print("統計情報の計算:")
for i, numbers in enumerate(test_cases, 1):
stats = calculate_statistics(numbers)
print(f"\nテストケース {i}: {numbers}")
for key, value in stats.items():
print(f" {key}: {value}")
# より詳細な統計情報を計算する拡張版
def calculate_detailed_statistics(numbers):
"""詳細な統計情報を計算する"""
if not numbers:
return {}
stats = calculate_statistics(numbers)
# 中央値の計算
sorted_numbers = sorted(numbers)
n = len(sorted_numbers)
if n % 2 == 0:
median = (sorted_numbers[n//2 - 1] + sorted_numbers[n//2]) / 2
else:
median = sorted_numbers[n//2]
stats["median"] = round(median, 2)
# 標準偏差の計算
mean = stats["average"]
variance = sum((x - mean) ** 2 for x in numbers) / len(numbers)
std_dev = variance ** 0.5
stats["std_dev"] = round(std_dev, 2)
return stats
# 詳細統計のテスト
print("\n詳細な統計情報:")
sample_data = [23, 45, 67, 12, 89, 34, 56]
detailed_stats = calculate_detailed_statistics(sample_data)
print(f"データ: {sample_data}")
for key, value in detailed_stats.items():
print(f"{key:>8}: {value}")
実行結果:
統計情報の計算:
テストケース 1: [1, 2, 3, 4, 5]
average: 3.0
max: 5
min: 1
sum: 15
count: 5
テストケース 2: [10, 20, 30, 40, 50]
average: 30.0
max: 50
min: 10
sum: 150
count: 5
テストケース 3: [2.5, 3.7, 1.8, 4.2, 5.1]
average: 3.46
max: 5.1
min: 1.8
sum: 17.3
count: 5
テストケース 4: [-5, -2, 0, 3, 7]
average: 0.6
max: 7
min: -5
sum: 3
count: 5
テストケース 5: []
average: 0
max: 0
min: 0
sum: 0
count: 0
テストケース 6: [42]
average: 42.0
max: 42
min: 42
sum: 42
count: 1
詳細な統計情報:
データ: [23, 45, 67, 12, 89, 34, 56]
average: 46.57
max: 89
min: 12
sum: 326
count: 7
median: 45.0
std_dev: 24.84
問題5 解答
def find_common_elements(list1, list2):
"""
2つのリストの共通要素を見つける
Parameters:
list1, list2 (list): 比較するリスト
Returns:
set: 共通要素の集合
"""
set1 = set(list1)
set2 = set(list2)
common = set1 & set2 # または set1.intersection(set2)
return common
# 関数のテスト
test_cases = [
([1, 2, 3, 4, 5], [4, 5, 6, 7, 8]),
(["apple", "banana", "orange"], ["banana", "grape", "kiwi"]),
([1, 2, 3], [4, 5, 6]),
([1, 2, 2, 3, 4], [2, 3, 3, 5, 6]), # 重複要素あり
([], [1, 2, 3]), # 空リスト
]
print("共通要素の検索:")
for i, (list1, list2) in enumerate(test_cases, 1):
common = find_common_elements(list1, list2)
print(f"\nテストケース {i}:")
print(f" リスト1: {list1}")
print(f" リスト2: {list2}")
print(f" 共通要素: {common}")
print(f" 共通要素数: {len(common)}")
# さまざまな集合演算を行う拡張関数
def perform_set_operations(list1, list2):
"""さまざまな集合演算を実行する"""
set1 = set(list1)
set2 = set(list2)
results = {
"set1": set1,
"set2": set2,
"union": set1 | set2, # 和集合
"intersection": set1 & set2, # 積集合
"difference1": set1 - set2, # 差集合 (set1 - set2)
"difference2": set2 - set1, # 差集合 (set2 - set1)
"symmetric_difference": set1 ^ set2 # 対称差集合
}
return results
# 集合演算のテスト
print("\n集合演算の例:")
list_a = [1, 2, 3, 4, 5]
list_b = [4, 5, 6, 7, 8]
operations = perform_set_operations(list_a, list_b)
print(f"リストA: {list_a}")
print(f"リストB: {list_b}")
for operation, result in operations.items():
print(f"{operation:>20}: {result}")
実行結果:
共通要素の検索:
テストケース 1:
リスト1: [1, 2, 3, 4, 5]
リスト2: [4, 5, 6, 7, 8]
共通要素: {4, 5}
共通要素数: 2
テストケース 2:
リスト1: ['apple', 'banana', 'orange']
リスト2: ['banana', 'grape', 'kiwi']
共通要素: {'banana'}
共通要素数: 1
テストケース 3:
リスト1: [1, 2, 3]
リスト2: [4, 5, 6]
共通要素: set()
共通要素数: 0
テストケース 4:
リスト1: [1, 2, 2, 3, 4]
リスト2: [2, 3, 3, 5, 6]
共通要素: {2, 3}
共通要素数: 2
テストケース 5:
リスト1: []
リスト2: [1, 2, 3]
共通要素: set()
共通要素数: 0
集合演算の例:
リストA: [1, 2, 3, 4, 5]
リストB: [4, 5, 6, 7, 8]
set1: {1, 2, 3, 4, 5}
set2: {4, 5, 6, 7, 8}
union: {1, 2, 3, 4, 5, 6, 7, 8}
intersection: {4, 5}
difference1: {1, 2, 3}
difference2: {8, 6, 7}
symmetric_difference: {1, 2, 3, 6, 7, 8}
問題6 解答
def count_word_frequency(text):
"""
文章から単語の頻度を計算する
Parameters:
text (str): 分析する文章
Returns:
dict: 単語とその出現回数の辞書
"""
# 句読点を除去し、小文字に変換して単語リストを作成
import string
translator = str.maketrans('', '', string.punctuation)
clean_text = text.translate(translator).lower()
words = clean_text.split()
word_freq = {}
for word in words:
if word: # 空文字列を除外
word_freq[word] = word_freq.get(word, 0) + 1
return word_freq
def analyze_text(text):
"""
文章を詳細に分析する
"""
word_freq = count_word_frequency(text)
total_words = sum(word_freq.values())
unique_words = len(word_freq)
# 出現回数でソート
sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
return {
"total_words": total_words,
"unique_words": unique_words,
"word_frequency": word_freq,
"most_common": sorted_words[:10], # 上位10語
"lexical_diversity": round(unique_words / total_words, 3) if total_words > 0 else 0
}
# テスト文章
sample_texts = [
"Hello world! Hello Python. Python is great. World of Python.",
"The quick brown fox jumps over the lazy dog. The dog was lazy but the fox was quick.",
"Data science is the future. Science and data are important for the future.",
"" # 空文字列
]
print("単語頻度分析:")
for i, text in enumerate(sample_texts, 1):
if not text:
print(f"\nテストケース {i}: 空文字列")
continue
analysis = analyze_text(text)
print(f"\nテストケース {i}:")
print(f" 文章: '{text}'")
print(f" 総単語数: {analysis['total_words']}")
print(f" ユニーク単語数: {analysis['unique_words']}")
print(f" 語彙の多様性: {analysis['lexical_diversity']}")
print(f" 最も頻出する単語:")
for word, count in analysis['most_common']:
print(f" {word}: {count}回")
# ストップワードを除去する拡張版
def count_word_frequency_advanced(text, remove_stopwords=True):
"""ストップワード除去機能付きの単語頻度計算"""
import string
# 英語のストップワードリスト
stopwords = {
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'have',
'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
'this', 'that', 'these', 'those', 'i', 'you', 'he', 'she', 'it', 'we', 'they'
}
translator = str.maketrans('', '', string.punctuation)
clean_text = text.translate(translator).lower()
words = clean_text.split()
word_freq = {}
for word in words:
if word and (not remove_stopwords or word not in stopwords):
word_freq[word] = word_freq.get(word, 0) + 1
return word_freq
# 拡張版のテスト
print("\n拡張版(ストップワード除去):")
text = "The quick brown fox jumps over the lazy dog. The dog was lazy but the fox was quick."
advanced_freq = count_word_frequency_advanced(text)
basic_freq = count_word_frequency(text)
print(f"元の文章: '{text}'")
print(f"基本版: {basic_freq}")
print(f"拡張版: {advanced_freq}")
実行結果:
単語頻度分析:
テストケース 1:
文章: 'Hello world! Hello Python. Python is great. World of Python.'
総単語数: 9
ユニーク単語数: 6
語彙の多様性: 0.667
最も頻出する単語:
hello: 2回
python: 3回
world: 1回
is: 1回
great: 1回
of: 1回
テストケース 2:
文章: 'The quick brown fox jumps over the lazy dog. The dog was lazy but the fox was quick.'
総単語数: 16
ユニーク単語数: 10
語彙の多様性: 0.625
最も頻出する単語:
the: 3回
lazy: 2回
fox: 2回
quick: 2回
dog: 2回
brown: 1回
jumps: 1回
over: 1回
was: 2回
but: 1回
テストケース 3:
文章: 'Data science is the future. Science and data are important for the future.'
総単語数: 12
ユニーク単語数: 9
語彙の多様性: 0.75
最も頻出する単語:
data: 1回
science: 2回
is: 1回
the: 2回
future: 2回
and: 1回
are: 1回
important: 1回
for: 1回
テストケース 4: 空文字列
拡張版(ストップワード除去):
元の文章: 'The quick brown fox jumps over the lazy dog. The dog was lazy but the fox was quick.'
基本版: {'the': 3, 'quick': 2, 'brown': 1, 'fox': 2, 'jumps': 1, 'over': 1, 'lazy': 2, 'dog': 2, 'was': 2, 'but': 1}
拡張版: {'quick': 2, 'brown': 1, 'fox': 2, 'jumps': 1, 'over': 1, 'lazy': 2, 'dog': 2}
問題7 解答
def manage_student_grades():
"""
学生の成績を管理するプログラム
"""
students = []
# サンプルデータの追加
sample_students = [
{"name": "Alice", "grades": {"Math": 85, "Science": 92, "English": 78}},
{"name": "Bob", "grades": {"Math": 76, "Science": 88, "English": 95}},
{"name": "Charlie", "grades": {"Math": 90, "Science": 85, "English": 92}},
{"name": "Diana", "grades": {"Math": 65, "Science": 70, "English": 75}},
]
students.extend(sample_students)
# 平均点の計算
for student in students:
grades = student["grades"].values()
student["average"] = sum(grades) / len(grades)
# 最高点と最低点の計算
all_grades = []
for student in students:
all_grades.extend(student["grades"].values())
overall_stats = {
"highest_score": max(all_grades),
"lowest_score": min(all_grades),
"overall_average": sum(all_grades) / len(all_grades)
}
# 成績順にソート
students_sorted = sorted(students, key=lambda x: x["average"], reverse=True)
return students_sorted, overall_stats
def display_student_results(students, stats):
"""学生の成績結果を表示する"""
print("学生成績一覧(成績順):")
print("-" * 60)
print(f"{'順位':<4} {'名前':<10} {'数学':<6} {'科学':<6} {'英語':<6} {'平均':<6}")
print("-" * 60)
for i, student in enumerate(students, 1):
grades = student["grades"]
print(f"{i:<4} {student['name']:<10} {grades['Math']:<6} {grades['Science']:<6} {grades['English']:<6} {student['average']:<6.1f}")
print("-" * 60)
print(f"全体統計:")
print(f" 最高点: {stats['highest_score']}")
print(f" 最低点: {stats['lowest_score']}")
print(f" 全体平均: {stats['overall_average']:.1f}")
# 科目ごとの統計を計算する関数
def calculate_subject_statistics(students):
"""科目ごとの統計を計算する"""
subjects = ["Math", "Science", "English"]
subject_stats = {}
for subject in subjects:
grades = [student["grades"][subject] for student in students]
subject_stats[subject] = {
"average": sum(grades) / len(grades),
"highest": max(grades),
"lowest": min(grades),
"count": len(grades)
}
return subject_stats
# プログラムの実行
students, overall_stats = manage_student_grades()
display_student_results(students, overall_stats)
# 科目ごとの統計を表示
print("\n科目ごとの統計:")
print("-" * 40)
subject_stats = calculate_subject_statistics(students)
for subject, stats in subject_stats.items():
print(f"{subject}:")
print(f" 平均: {stats['average']:.1f}")
print(f" 最高: {stats['highest']}")
print(f" 最低: {stats['lowest']}")
print(f" 人数: {stats['count']}")
実行結果:
学生成績一覧(成績順):
------------------------------------------------------------
順位 名前 数学 科学 英語 平均
------------------------------------------------------------
1 Charlie 90 85 92 89.0
2 Alice 85 92 78 85.0
3 Bob 76 88 95 86.3
4 Diana 65 70 75 70.0
------------------------------------------------------------
全体統計:
最高点: 95
最低点: 65
全体平均: 82.6
科目ごとの統計:
----------------------------------------
Math:
平均: 79.0
最高: 90
最低: 65
人数: 4
Science:
平均: 83.8
最高: 92
最低: 70
人数: 4
English:
平均: 85.0
最高: 95
最低: 75
人数: 4
問題8 解答
import math
# 1. 1から20までの偶数のリスト
even_numbers = [x for x in range(1, 21) if x % 2 == 0]
print(f"1から20までの偶数: {even_numbers}")
# 2. 1から10までの数の平方根のリスト(小数第2位まで)
square_roots = [round(math.sqrt(x), 2) for x in range(1, 11)]
print(f"1から10までの平方根: {square_roots}")
# 3. 与えられた文字列リストから、長さが5文字以上の文字列だけを抽出
words = ["apple", "cat", "elephant", "dog", "computer", "hi", "programming"]
long_words = [word for word in words if len(word) >= 5]
print(f"5文字以上の単語: {long_words}")
# 追加のリスト内包表記の例
print("\n追加のリスト内包表記の例:")
# 4. 文字列のリストを大文字に変換
uppercase_words = [word.upper() for word in words]
print(f"大文字変換: {uppercase_words}")
# 5. 数値の二乗と三乗を同時に計算
numbers = [1, 2, 3, 4, 5]
squares_and_cubes = [(x, x**2, x**3) for x in numbers]
print(f"数値、二乗、三乗: {squares_and_cubes}")
# 6. ネストしたリスト内包表記(九九の表)
multiplication_table = [[i * j for j in range(1, 10)] for i in range(1, 10)]
print("\n九九の表(リスト内包表記):")
for row in multiplication_table:
for num in row:
print(f"{num:2d}", end=" ")
print()
# 7. 条件付きの複雑なリスト内包表記
mixed_data = [1, "hello", 3.14, 42, "world", 2.71, "python"]
numbers_only = [x for x in mixed_data if isinstance(x, (int, float))]
strings_only = [x for x in mixed_data if isinstance(x, str)]
print(f"\n混合データ: {mixed_data}")
print(f"数値のみ: {numbers_only}")
print(f"文字列のみ: {strings_only}")
# 8. 辞書内包表記の例
word_lengths = {word: len(word) for word in words}
print(f"\n単語とその長さ: {word_lengths}")
# 9. 集合内包表記の例
unique_lengths = {len(word) for word in words}
print(f"ユニークな単語の長さ: {unique_lengths}")
実行結果:
1から20までの偶数: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
1から10までの平方根: [1.0, 1.41, 1.73, 2.0, 2.24, 2.45, 2.65, 2.83, 3.0, 3.16]
5文字以上の単語: ['apple', 'elephant', 'computer', 'programming']
追加のリスト内包表記の例:
大文字変換: ['APPLE', 'CAT', 'ELEPHANT', 'DOG', 'COMPUTER', 'HI', 'PROGRAMMING']
数値、二乗、三乗: [(1, 1, 1), (2, 4, 8), (3, 9, 27), (4, 16, 64), (5, 25, 125)]
九九の表(リスト内包表記):
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
混合データ: [1, 'hello', 3.14, 42, 'world', 2.71, 'python']
数値のみ: [1, 3.14, 42, 2.71]
文字列のみ: ['hello', 'world', 'python']
単語とその長さ: {'apple': 5, 'cat': 3, 'elephant': 8, 'dog': 3, 'computer': 8, 'hi': 2, 'programming': 11}
ユニークな単語の長さ: {2, 3, 5, 8, 11}
問題9 解答
def merge_dicts(dict1, dict2):
"""
2つの辞書を結合する。同じキーがある場合はdict2の値で上書き
Parameters:
dict1, dict2 (dict): 結合する辞書
Returns:
dict: 結合された辞書
"""
# 方法1: updateメソッドを使用
result = dict1.copy() # 元の辞書を変更しないようにコピー
result.update(dict2)
return result
def merge_dicts_v2(dict1, dict2):
"""
2つの辞書を結合する(別の方法)
"""
# 方法2: 辞書内包表記を使用
return {**dict1, **dict2}
def merge_dicts_v3(dict1, dict2):
"""
2つの辞書を結合する(Python 3.9以降)
"""
# 方法3: | 演算子を使用(Python 3.9以降)
return dict1 | dict2
# 関数のテスト
test_cases = [
({"a": 1, "b": 2}, {"c": 3, "d": 4}), # 重複キーなし
({"a": 1, "b": 2}, {"b": 20, "c": 3}), # 重複キーあり
({}, {"a": 1, "b": 2}), # 空の辞書
({"x": 10}, {}), # 空の辞書
({"name": "Alice", "age": 25}, {"age": 26, "city": "Tokyo"}), # 実際的な例
]
print("辞書の結合テスト:")
for i, (dict1, dict2) in enumerate(test_cases, 1):
merged = merge_dicts(dict1, dict2)
print(f"\nテストケース {i}:")
print(f" 辞書1: {dict1}")
print(f" 辞書2: {dict2}")
print(f" 結合後: {merged}")
# 複数の辞書を結合する関数
def merge_multiple_dicts(*dicts):
"""
複数の辞書を結合する
Parameters:
*dicts: 結合する辞書(可変長引数)
Returns:
dict: 結合された辞書
"""
result = {}
for d in dicts:
result.update(d)
return result
# 複数辞書の結合テスト
print("\n複数辞書の結合:")
dict_a = {"a": 1, "b": 2}
dict_b = {"b": 20, "c": 3}
dict_c = {"c": 30, "d": 4}
dict_d = {"e": 5}
merged_multiple = merge_multiple_dicts(dict_a, dict_b, dict_c, dict_d)
print(f"辞書A: {dict_a}")
print(f"辞書B: {dict_b}")
print(f"辞書C: {dict_c}")
print(f"辞書D: {dict_d}")
print(f"結合後: {merged_multiple}")
# カスタムマージロジックを持つ関数
def merge_dicts_custom(dict1, dict2, merge_func=None):
"""
カスタムマージロジックで辞書を結合する
Parameters:
dict1, dict2: 結合する辞書
merge_func: 重複キーの値をどうするかを決める関数
"""
result = dict1.copy()
for key, value in dict2.items():
if key in result and merge_func:
result[key] = merge_func(result[key], value)
else:
result[key] = value
return result
# カスタムマージのテスト
print("\nカスタムマージの例:")
# 数値の場合は加算するマージ関数
def sum_values(v1, v2):
return v1 + v2
# リストの場合は結合するマージ関数
def extend_lists(v1, v2):
if isinstance(v1, list) and isinstance(v2, list):
return v1 + v2
return v2 # 型が違う場合は上書き
dict1 = {"a": 10, "b": [1, 2], "c": 100}
dict2 = {"a": 5, "b": [3, 4], "d": 200}
merged_sum = merge_dicts_custom(dict1, dict2, sum_values)
merged_extend = merge_dicts_custom(dict1, dict2, extend_lists)
print(f"辞書1: {dict1}")
print(f"辞書2: {dict2}")
print(f"数値加算マージ: {merged_sum}")
print(f"リスト結合マージ: {merged_extend}")
実行結果:
辞書の結合テスト:
テストケース 1:
辞書1: {'a': 1, 'b': 2}
辞書2: {'c': 3, 'd': 4}
結合後: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
テストケース 2:
辞書1: {'a': 1, 'b': 2}
辞書2: {'b': 20, 'c': 3}
結合後: {'a': 1, 'b': 20, 'c': 3}
テストケース 3:
辞書1: {}
辞書2: {'a': 1, 'b': 2}
結合後: {'a': 1, 'b': 2}
テストケース 4:
辞書1: {'x': 10}
辞書2: {}
結合後: {'x': 10}
テストケース 5:
辞書1: {'name': 'Alice', 'age': 25}
辞書2: {'age': 26, 'city': 'Tokyo'}
結合後: {'name': 'Alice', 'age': 26, 'city': 'Tokyo'}
複数辞書の結合:
辞書A: {'a': 1, 'b': 2}
辞書B: {'b': 20, 'c': 3}
辞書C: {'c': 30, 'd': 4}
辞書D: {'e': 5}
結合後: {'a': 1, 'b': 20, 'c': 30, 'd': 4, 'e': 5}
カスタムマージの例:
辞書1: {'a': 10, 'b': [1, 2], 'c': 100}
辞書2: {'a': 5, 'b': [3, 4], 'd': 200}
数値加算マージ: {'a': 15, 'b': [1, 2], 'c': 100, 'd': 200}
リスト結合マージ: {'a': 5, 'b': [1, 2, 3, 4], 'c': 100, 'd': 200}
上級問題 解答
問題10 解答
def matrix_addition(matrix1, matrix2):
"""
行列の加算を行う
Parameters:
matrix1, matrix2 (list): 2次元リストで表現された行列
Returns:
list: 加算結果の行列
Raises:
ValueError: 行列の次元が一致しない場合
"""
# 次元のチェック
if len(matrix1) != len(matrix2) or len(matrix1[0]) != len(matrix2[0]):
raise ValueError("行列の次元が一致しません")
rows = len(matrix1)
cols = len(matrix1[0])
# 結果行列の初期化
result = [[0 for _ in range(cols)] for _ in range(rows)]
# 加算の実行
for i in range(rows):
for j in range(cols):
result[i][j] = matrix1[i][j] + matrix2[i][j]
return result
def matrix_multiplication(matrix1, matrix2):
"""
行列の乗算を行う
Parameters:
matrix1, matrix2 (list): 2次元リストで表現された行列
Returns:
list: 乗算結果の行列
Raises:
ValueError: 行列の次元が乗算できない場合
"""
# 次元のチェック
if len(matrix1[0]) != len(matrix2):
raise ValueError("行列の次元が乗算できません")
rows1 = len(matrix1)
cols1 = len(matrix1[0])
cols2 = len(matrix2[0])
# 結果行列の初期化
result = [[0 for _ in range(cols2)] for _ in range(rows1)]
# 乗算の実行
for i in range(rows1):
for j in range(cols2):
for k in range(cols1):
result[i][j] += matrix1[i][k] * matrix2[k][j]
return result
def print_matrix(matrix, name="行列"):
"""行列を整形して表示する"""
print(f"{name}:")
for row in matrix:
print(" [", end="")
for j, element in enumerate(row):
if j > 0:
print(", ", end="")
print(f"{element:4}", end="")
print("]")
print()
# 行列演算のテスト
print("=== 行列演算のテスト ===")
# テスト用の行列
A = [
[1, 2, 3],
[4, 5, 6]
]
B = [
[7, 8],
[9, 10],
[11, 12]
]
C = [
[1, 2],
[3, 4]
]
D = [
[5, 6],
[7, 8]
]
E = [
[1, 2, 3],
[4, 5, 6]
]
# 行列の表示
print_matrix(A, "行列A")
print_matrix(B, "行列B")
print_matrix(C, "行列C")
print_matrix(D, "行列D")
# 行列の加算
try:
addition_result = matrix_addition(C, D)
print_matrix(addition_result, "C + D")
except ValueError as e:
print(f"加算エラー: {e}")
# 行列の乗算
try:
multiplication_result = matrix_multiplication(A, B)
print_matrix(multiplication_result, "A × B")
except ValueError as e:
print(f"乗算エラー: {e}")
# エラーハンドリングのテスト
print("エラーハンドリングのテスト:")
try:
invalid_addition = matrix_addition(A, C) # 次元不一致
except ValueError as e:
print(f"加算エラー: {e}")
try:
invalid_multiplication = matrix_multiplication(C, A) # 次元不一致
except ValueError as e:
print(f"乗算エラー: {e}")
# 単位行列の乗算テスト
identity_2x2 = [
[1, 0],
[0, 1]
]
print("単位行列のテスト:")
print_matrix(identity_2x2, "単位行列 I")
try:
identity_result = matrix_multiplication(C, identity_2x2)
print_matrix(identity_result, "C × I")
print("C × I == C:", identity_result == C)
except ValueError as e:
print(f"エラー: {e}")
# ゼロ行列のテスト
zero_2x2 = [
[0, 0],
[0, 0]
]
print("ゼロ行列のテスト:")
print_matrix(zero_2x2, "ゼロ行列 Z")
try:
zero_result = matrix_addition(C, zero_2x2)
print_matrix(zero_result, "C + Z")
print("C + Z == C:", zero_result == C)
except ValueError as e:
print(f"エラー: {e}")
実行結果:
=== 行列演算のテスト ===
行列A:
[ 1, 2, 3]
[ 4, 5, 6]
行列B:
[ 7, 8]
[ 9, 10]
[ 11, 12]
行列C:
[ 1, 2]
[ 3, 4]
行列D:
[ 5, 6]
[ 7, 8]
C + D:
[ 6, 8]
[ 10, 12]
A × B:
[ 58, 64]
[ 139, 154]
エラーハンドリングのテスト:
加算エラー: 行列の次元が一致しません
乗算エラー: 行列の次元が乗算できません
単位行列のテスト:
単位行列 I:
[ 1, 0]
[ 0, 1]
C × I:
[ 1, 2]
[ 3, 4]
C × I == C: True
ゼロ行列のテスト:
ゼロ行列 Z:
[ 0, 0]
[ 0, 0]
C + Z:
[ 1, 2]
[ 3, 4]
C + Z == C: True
問題11 解答
class ShoppingCart:
"""ショッピングカートシステム"""
def __init__(self):
self.items = {} # {商品名: (価格, 数量)}
def add_item(self, name, price, quantity=1):
"""商品をカートに追加する"""
if quantity <= 0:
print("数量は1以上で指定してください")
return
if name in self.items:
# 既存の商品の場合、数量を追加
current_price, current_quantity = self.items[name]
self.items[name] = (current_price, current_quantity + quantity)
print(f"'{name}' の数量を {quantity} 追加しました")
else:
# 新しい商品の場合、追加
self.items[name] = (price, quantity)
print(f"'{name}' を {quantity} 個追加しました")
def remove_item(self, name, quantity=None):
"""商品をカートから削除する"""
if name not in self.items:
print(f"'{name}' はカートにありません")
return
current_price, current_quantity = self.items[name]
if quantity is None or quantity >= current_quantity:
# 数量指定なしまたは全削除の場合
del self.items[name]
print(f"'{name}' をカートから削除しました")
else:
# 一部削除の場合
self.items[name] = (current_price, current_quantity - quantity)
print(f"'{name}' の数量を {quantity} 減らしました")
def update_quantity(self, name, new_quantity):
"""商品の数量を更新する"""
if name not in self.items:
print(f"'{name}' はカートにありません")
return
if new_quantity <= 0:
self.remove_item(name)
return
current_price, _ = self.items[name]
self.items[name] = (current_price, new_quantity)
print(f"'{name}' の数量を {new_quantity} に更新しました")
def calculate_total(self):
"""合計金額を計算する"""
total = 0
for name, (price, quantity) in self.items.items():
total += price * quantity
return total
def display_cart(self):
"""カートの内容を表示する"""
if not self.items:
print("カートは空です")
return
print("\nショッピングカートの内容:")
print("-" * 50)
print(f"{'商品名':<15} {'単価':<8} {'数量':<8} {'小計':<10}")
print("-" * 50)
for name, (price, quantity) in self.items.items():
subtotal = price * quantity
print(f"{name:<15} {price:<8} {quantity:<8} {subtotal:<10}")
print("-" * 50)
total = self.calculate_total()
print(f"{'合計金額':<33} {total:<10}")
def get_item_count(self):
"""カート内の商品種類数を返す"""
return len(self.items)
def get_total_quantity(self):
"""カート内の総商品数を返す"""
return sum(quantity for _, (_, quantity) in self.items.items())
def clear_cart(self):
"""カートを空にする"""
self.items.clear()
print("カートを空にしました")
# ショッピングカートの使用例
def demo_shopping_cart():
"""ショッピングカートのデモンストレーション"""
cart = ShoppingCart()
print("=== ショッピングカートデモ ===")
# 商品の追加
cart.add_item("りんご", 100, 3)
cart.add_item("バナナ", 80, 2)
cart.add_item("オレンジ", 120, 1)
cart.add_item("りんご", 100, 2) # 既存商品の追加
cart.display_cart()
print(f"商品種類数: {cart.get_item_count()}")
print(f"総商品数: {cart.get_total_quantity()}")
# 数量の更新
print("\n--- 数量の更新 ---")
cart.update_quantity("バナナ", 5)
cart.display_cart()
# 商品の削除
print("\n--- 商品の削除 ---")
cart.remove_item("オレンジ")
cart.remove_item("りんご", 2) # 一部削除
cart.display_cart()
# エラーハンドリング
print("\n--- エラーハンドリング ---")
cart.remove_item("存在しない商品") # 存在しない商品
cart.update_quantity("存在しない商品", 5) # 存在しない商品
cart.add_item("ぶどう", 200, 0) # 無効な数量
# カートを空にする
print("\n--- カートのクリア ---")
cart.clear_cart()
cart.display_cart()
# インタラクティブなショッピングカート
def interactive_shopping_cart():
"""インタラクティブなショッピングカート"""
cart = ShoppingCart()
print("=== インタラクティブショッピングカート ===")
print("利用可能なコマンド:")
print(" add <商品名> <価格> [数量] - 商品を追加")
print(" remove <商品名> [数量] - 商品を削除")
print(" update <商品名> <数量> - 数量を更新")
print(" show - カートを表示")
print(" clear - カートを空にする")
print(" total - 合計金額を表示")
print(" quit - 終了")
while True:
try:
command = input("\nコマンドを入力してください: ").strip().split()
if not command:
continue
action = command[0].lower()
if action == "quit":
print("ショッピングカートを終了します")
break
elif action == "show":
cart.display_cart()
elif action == "clear":
cart.clear_cart()
elif action == "total":
total = cart.calculate_total()
print(f"合計金額: {total}円")
elif action == "add" and len(command) >= 3:
name = command[1]
price = float(command[2])
quantity = int(command[3]) if len(command) > 3 else 1
cart.add_item(name, price, quantity)
elif action == "remove" and len(command) >= 2:
name = command[1]
quantity = int(command[2]) if len(command) > 2 else None
cart.remove_item(name, quantity)
elif action == "update" and len(command) >= 3:
name = command[1]
quantity = int(command[2])
cart.update_quantity(name, quantity)
else:
print("無効なコマンドです。ヘルプを表示するには 'help' と入力してください")
except ValueError:
print("数値の形式が正しくありません")
except Exception as e:
print(f"エラーが発生しました: {e}")
# デモの実行
if __name__ == "__main__":
demo_shopping_cart()
print("\n" + "="*50)
# インタラクティブモードを実行する場合は以下のコメントを外す
# interactive_shopping_cart()
実行結果:
=== ショッピングカートデモ ===
'りんご' を 3 個追加しました
'バナナ' を 2 個追加しました
'オレンジ' を 1 個追加しました
'りんご' の数量を 2 追加しました
ショッピングカートの内容:
--------------------------------------------------
商品名 単価 数量 小計
--------------------------------------------------
りんご 100 5 500
バナナ 80 2 160
オレンジ 120 1 120
--------------------------------------------------
合計金額 780
商品種類数: 3
総商品数: 8
--- 数量の更新 ---
'バナナ' の数量を 5 に更新しました
ショッピングカートの内容:
--------------------------------------------------
商品名 単価 数量 小計
--------------------------------------------------
りんご 100 5 500
バナナ 80 5 400
オレンジ 120 1 120
--------------------------------------------------
合計金額 1020
商品種類数: 3
総商品数: 11
--- 商品の削除 ---
'オレンジ' をカートから削除しました
'りんご' の数量を 2 減らしました
ショッピングカートの内容:
--------------------------------------------------
商品名 単価 数量 小計
--------------------------------------------------
りんご 100 3 300
バナナ 80 5 400
--------------------------------------------------
合計金額 700
--- エラーハンドリング ---
'存在しない商品' はカートにありません
'存在しない商品' はカートにありません
数量は1以上で指定してください
--- カートのクリア ---
カートを空にしました
カートは空です
==================================================
問題12 解答
def analyze_student_data(students_data):
"""
学生データを分析する
Parameters:
students_data (list): 学生データのリスト
[{"name": str, "subjects": {subject: score}}]
Returns:
dict: 分析結果
"""
if not students_data:
return {}
# すべての科目を収集
all_subjects = set()
for student in students_data:
all_subjects.update(student["subjects"].keys())
all_subjects = sorted(all_subjects)
# 科目ごとの統計
subject_stats = {}
for subject in all_subjects:
scores = []
for student in students_data:
if subject in student["subjects"]:
scores.append(student["subjects"][subject])
if scores:
subject_stats[subject] = {
"average": sum(scores) / len(scores),
"max": max(scores),
"min": min(scores),
"count": len(scores),
"scores": scores
}
# 学生ごとの平均点
student_averages = []
for student in students_data:
scores = list(student["subjects"].values())
average = sum(scores) / len(scores)
student_averages.append({
"name": student["name"],
"average": average,
"subjects": student["subjects"]
})
# 成績順位の計算
sorted_students = sorted(student_averages, key=lambda x: x["average"], reverse=True)
for i, student in enumerate(sorted_students, 1):
student["rank"] = i
# 成績分布の計算
grade_distribution = {}
for subject in all_subjects:
scores = subject_stats[subject]["scores"]
distribution = {
"90-100": len([s for s in scores if s >= 90]),
"80-89": len([s for s in scores if 80 <= s < 90]),
"70-79": len([s for s in scores if 70 <= s < 80]),
"60-69": len([s for s in scores if 60 <= s < 70]),
"0-59": len([s for s in scores if s < 60])
}
grade_distribution[subject] = distribution
return {
"subject_stats": subject_stats,
"student_rankings": sorted_students,
"grade_distribution": grade_distribution,
"overall_average": sum(s["average"] for s in student_averages) / len(student_averages)
}
def display_analysis_results(analysis):
"""分析結果を表示する"""
if not analysis:
print("分析するデータがありません")
return
print("=== 学生データ分析結果 ===\n")
# 全体統計
print(f"全体平均点: {analysis['overall_average']:.1f}点")
print(f"分析対象学生数: {len(analysis['student_rankings'])}名")
print(f"科目数: {len(analysis['subject_stats'])}科目\n")
# 科目ごとの統計
print("科目ごとの統計:")
print("-" * 60)
print(f"{'科目':<12} {'平均':<6} {'最高':<6} {'最低':<6} {'受験者数':<8}")
print("-" * 60)
for subject, stats in analysis["subject_stats"].items():
print(f"{subject:<12} {stats['average']:<6.1f} {stats['max']:<6} {stats['min']:<6} {stats['count']:<8}")
# 学生の成績順位
print(f"\n学生の成績順位:")
print("-" * 80)
print(f"{'順位':<4} {'名前':<10} {'平均点':<6} {'科目と点数':<40}")
print("-" * 80)
for student in analysis["student_rankings"]:
subjects_str = ", ".join([f"{sub}:{score}" for sub, score in student["subjects"].items()])
print(f"{student['rank']:<4} {student['name']:<10} {student['average']:<6.1f} {subjects_str:<40}")
# 成績分布
print(f"\n成績分布:")
print("-" * 70)
header = f"{'科目':<12} {'90-100':<8} {'80-89':<8} {'70-79':<8} {'60-69':<8} {'0-59':<8}"
print(header)
print("-" * 70)
for subject, distribution in analysis["grade_distribution"].items():
row = f"{subject:<12}"
for grade_range in ["90-100", "80-89", "70-79", "60-69", "0-59"]:
row += f"{distribution[grade_range]:<8}"
print(row)
# サンプルデータ
sample_students = [
{
"name": "Alice",
"subjects": {
"数学": 85,
"英語": 92,
"科学": 78,
"歴史": 88
}
},
{
"name": "Bob",
"subjects": {
"数学": 76,
"英語": 88,
"科学": 95,
"歴史": 82
}
},
{
"name": "Charlie",
"subjects": {
"数学": 90,
"英語": 85,
"科学": 92,
"歴史": 79
}
},
{
"name": "Diana",
"subjects": {
"数学": 65,
"英語": 70,
"科学": 75,
"歴史": 68
}
},
{
"name": "Eve",
"subjects": {
"数学": 95,
"英語": 98,
"科学": 92,
"歴史": 96
}
}
]
# 分析の実行
print("学生データ分析プログラム")
print("=" * 50)
analysis_results = analyze_student_data(sample_students)
display_analysis_results(analysis_results)
# 追加の詳細分析
def detailed_subject_analysis(analysis):
"""科目ごとの詳細分析"""
print(f"\n科目ごとの詳細分析:")
print("=" * 50)
for subject, stats in analysis["subject_stats"].items():
print(f"\n{subject}:")
print(f" 平均点: {stats['average']:.1f}")
print(f" 最高点: {stats['max']}")
print(f" 最低点: {stats['min']}")
print(f" 点数の範囲: {stats['max'] - stats['min']}")
print(f" 受験者数: {stats['count']}")
# 標準偏差の計算
scores = stats['scores']
mean = stats['average']
variance = sum((x - mean) ** 2 for x in scores) / len(scores)
std_dev = variance ** 0.5
print(f" 標準偏差: {std_dev:.2f}")
# 詳細分析の実行
detailed_subject_analysis(analysis_results)
# 優秀な学生の特定
def identify_top_students(analysis, threshold=85):
"""特定の閾値以上の平均点の学生を特定する"""
print(f"\n平均点{threshold}点以上の優秀な学生:")
print("-" * 40)
top_students = [s for s in analysis["student_rankings"] if s["average"] >= threshold]
if top_students:
for student in top_students:
print(f"{student['name']}: {student['average']:.1f}点 (順位: {student['rank']}位)")
else:
print(f"平均点{threshold}点以上の学生はいません")
# 優秀な学生の特定
identify_top_students(analysis_results, 85)
実行結果:
学生データ分析プログラム
==================================================
=== 学生データ分析結果 ===
全体平均点: 83.4点
分析対象学生数: 5名
科目数: 4科目
科目ごとの統計:
------------------------------------------------------------
科目 平均 最高 最低 受験者数
------------------------------------------------------------
数学 82.2 95 65 5
英語 86.6 98 70 5
科学 86.4 95 75 5
歴史 82.6 96 68 5
学生の成績順位:
--------------------------------------------------------------------------------
順位 名前 平均点 科目と点数
--------------------------------------------------------------------------------
1 Eve 95.2 数学:95,英語:98,科学:92,歴史:96
2 Alice 85.8 数学:85,英語:92,科学:78,歴史:88
3 Charlie 86.5 数学:90,英語:85,科学:92,歴史:79
4 Bob 85.2 数学:76,英語:88,科学:95,歴史:82
5 Diana 69.5 数学:65,英語:70,科学:75,歴史:68
成績分布:
----------------------------------------------------------------------
科目 90-100 80-89 70-79 60-69 0-59
----------------------------------------------------------------------
数学 1 2 1 1 0
英語 2 2 1 0 0
科学 2 2 1 0 0
歴史 1 2 1 1 0
科目ごとの詳細分析:
==================================================
数学:
平均点: 82.2
最高点: 95
最低点: 65
点数の範囲: 30
受験者数: 5
標準偏差: 11.36
英語:
平均点: 86.6
最高点: 98
最低点: 70
点数の範囲: 28
受験者数: 5
標準偏差: 10.50
科学:
平均点: 86.4
最高点: 95
最低点: 75
点数の範囲: 20
受験者数: 5
標準偏差: 8.53
歴史:
平均点: 82.6
最高点: 96
最低点: 68
点数の範囲: 28
受験者数: 5
標準偏差: 10.50
平均点85点以上の優秀な学生:
----------------------------------------
Eve: 95.2点 (順位: 1位)
Alice: 85.8点 (順位: 2位)
Charlie: 86.5点 (順位: 3位)
Bob: 85.2点 (順位: 4位)