Lesson6 / 6
演習:辞書の総合問題
目次
1. このレッスンで学ぶこと
- 辞書を使った実践的な演習
- データの集計と分析
- 複合的な問題の解決
- 実務に近いコーディング
2. なぜ演習が必要か?
辞書の操作を理解しただけでは、実際の問題解決には不十分です。
Python# 理論だけでは不十分 理論 = "辞書はキーと値のペア" # 実践で初めて理解が深まる 実践 = "データを効率的に管理・分析できる"
演習を通じて、辞書の実践力を身につけましょう。
💡 豆知識: 実務では、辞書はJSON APIのレスポンス処理、データベースレコードの表現、設定管理など、あらゆる場面で使われます。辞書を使いこなせることは、Pythonプログラマーにとって必須のスキルです。
3. 演習1: 在庫管理システム
問題
以下の商品在庫データを管理するシステムを作成してください。
Python# 商品在庫データ inventory = { "apple": {"price": 100, "stock": 50}, "banana": {"price": 80, "stock": 30}, "orange": {"price": 120, "stock": 20} } # 実装する機能: # 1. 商品を追加する関数 # 2. 在庫を更新する関数 # 3. 商品を削除する関数 # 4. 在庫切れ商品を確認する関数 # 5. 在庫総額を計算する関数
💡 ヒント
- 関数を使って機能を分ける
- 存在確認をしてからアクセス
- ループで全商品を処理
✅ 解答例
Pythoninventory = { "apple": {"price": 100, "stock": 50}, "banana": {"price": 80, "stock": 30}, "orange": {"price": 120, "stock": 20} } # 機能1: 商品を追加 def add_product(name, price, stock): if name in inventory: print(f"{name}は既に存在します") else: inventory[name] = {"price": price, "stock": stock} print(f"{name}を追加しました") # 機能2: 在庫を更新 def update_stock(name, quantity): if name in inventory: inventory[name]["stock"] += quantity new_stock = inventory[name]["stock"] print(f"{name}の在庫を更新: {new_stock}個") else: print(f"{name}が見つかりません") # 機能3: 商品を削除 def remove_product(name): if name in inventory: removed = inventory.pop(name) print(f"{name}を削除しました(価格: {removed['price']}円)") else: print(f"{name}が見つかりません") # 機能4: 在庫切れ確認 def check_out_of_stock(): out_of_stock = [] for name, info in inventory.items(): if info["stock"] == 0: out_of_stock.append(name) if out_of_stock: print(f"在庫切れ: {', '.join(out_of_stock)}") else: print("在庫切れ商品なし") return out_of_stock # 機能5: 在庫総額を計算 def calculate_total_value(): total = 0 for name, info in inventory.items(): value = info["price"] * info["stock"] total += value print(f"{name}: {info['price']}円 × {info['stock']}個 = {value:,}円") return total # テスト実行 print("=== 初期在庫 ===") for name, info in inventory.items(): print(f"{name}: {info['price']}円, 在庫{info['stock']}個") print("\n=== 商品追加 ===") add_product("grape", 200, 15) print("\n=== 在庫更新 ===") update_stock("apple", -10) update_stock("banana", 20) print("\n=== 在庫総額 ===") total = calculate_total_value() print(f"総額: {total:,}円") print("\n=== 在庫切れ確認 ===") check_out_of_stock() print("\n=== 商品削除 ===") remove_product("orange") print("\n=== 最終在庫 ===") for name, info in inventory.items(): print(f"{name}: {info['price']}円, 在庫{info['stock']}個")
実行結果:
=== 初期在庫 ===
apple: 100円, 在庫50個
banana: 80円, 在庫30個
orange: 120円, 在庫20個
=== 商品追加 ===
grapeを追加しました
=== 在庫更新 ===
appleの在庫を更新: 40個
bananaの在庫を更新: 50個
=== 在庫総額 ===
apple: 100円 × 40個 = 4,000円
banana: 80円 × 50個 = 4,000円
orange: 120円 × 20個 = 2,400円
grape: 200円 × 15個 = 3,000円
総額: 13,400円
=== 在庫切れ確認 ===
在庫切れ商品なし
=== 商品削除 ===
orangeを削除しました(価格: 120円)
=== 最終在庫 ===
apple: 100円, 在庫40個
banana: 80円, 在庫50個
grape: 200円, 在庫15個
4. 演習2: 成績管理システム
問題
生徒の成績データを管理し、以下の分析を行ってください。
Python# 生徒の成績データ students = { "太郎": {"math": 85, "english": 92, "science": 78}, "花子": {"math": 95, "english": 88, "science": 90}, "次郎": {"math": 72, "english": 85, "science": 80}, "三郎": {"math": 88, "english": 78, "science": 85} } # 実装する機能: # 1. 各生徒の平均点を計算 # 2. 科目別の平均点を計算 # 3. 最高点と最低点を持つ生徒を見つける # 4. 全科目80点以上の生徒を抽出
✅ 解答例
Pythonstudents = { "太郎": {"math": 85, "english": 92, "science": 78}, "花子": {"math": 95, "english": 88, "science": 90}, "次郎": {"math": 72, "english": 85, "science": 80}, "三郎": {"math": 88, "english": 78, "science": 85} } # 機能1: 各生徒の平均点 print("=== 生徒別平均点 ===") student_averages = {} for name, scores in students.items(): total = sum(scores.values()) average = total / len(scores) student_averages[name] = average print(f"{name}: {average:.2f}点") # 機能2: 科目別平均点 print("\n=== 科目別平均点 ===") subjects = ["math", "english", "science"] subject_averages = {} for subject in subjects: total = 0 count = 0 for scores in students.values(): total += scores[subject] count += 1 average = total / count subject_averages[subject] = average print(f"{subject}: {average:.2f}点") # 機能3: 最高点・最低点の生徒 print("\n=== 最高点・最低点 ===") max_student = max(student_averages.items(), key=lambda x: x[1]) min_student = min(student_averages.items(), key=lambda x: x[1]) print(f"最高平均: {max_student[0]} ({max_student[1]:.2f}点)") print(f"最低平均: {min_student[0]} ({min_student[1]:.2f}点)") # 機能4: 全科目80点以上 print("\n=== 全科目80点以上の生徒 ===") excellent_students = [] for name, scores in students.items(): if all(score >= 80 for score in scores.values()): excellent_students.append(name) print(f"{name}: {scores}") if not excellent_students: print("該当者なし") # 追加分析: 科目別最高得点者 print("\n=== 科目別最高得点者 ===") for subject in subjects: max_score = 0 top_student = "" for name, scores in students.items(): if scores[subject] > max_score: max_score = scores[subject] top_student = name print(f"{subject}: {top_student} ({max_score}点)") # 全体統計 all_scores = [] for scores in students.values(): all_scores.extend(scores.values()) print(f"\n=== 全体統計 ===") print(f"総合平均: {sum(all_scores) / len(all_scores):.2f}点") print(f"最高点: {max(all_scores)}点") print(f"最低点: {min(all_scores)}点")
実行結果:
=== 生徒別平均点 ===
太郎: 85.00点
花子: 91.00点
次郎: 79.00点
三郎: 83.67点
=== 科目別平均点 ===
math: 85.00点
english: 85.75点
science: 83.25点
=== 最高点・最低点 ===
最高平均: 花子 (91.00点)
最低平均: 次郎 (79.00点)
=== 全科目80点以上の生徒 ===
花子: {'math': 95, 'english': 88, 'science': 90}
=== 科目別最高得点者 ===
math: 花子 (95点)
english: 太郎 (92点)
science: 花子 (90点)
=== 全体統計 ===
総合平均: 84.67点
最高点: 95点
最低点: 72点
5. 演習3: アクセスログ分析
問題
Webサイトのアクセスログを分析してください。
Python# アクセスログデータ logs = [ {"user": "user001", "page": "/home", "time": "10:00"}, {"user": "user002", "page": "/about", "time": "10:05"}, {"user": "user001", "page": "/products", "time": "10:10"}, {"user": "user003", "page": "/home", "time": "10:15"}, {"user": "user001", "page": "/contact", "time": "10:20"}, {"user": "user002", "page": "/home", "time": "10:25"} ] # 分析内容: # 1. ユーザー別アクセス回数 # 2. ページ別アクセス回数 # 3. 最もアクティブなユーザー # 4. 最も人気のあるページ
✅ 解答例
Pythonlogs = [ {"user": "user001", "page": "/home", "time": "10:00"}, {"user": "user002", "page": "/about", "time": "10:05"}, {"user": "user001", "page": "/products", "time": "10:10"}, {"user": "user003", "page": "/home", "time": "10:15"}, {"user": "user001", "page": "/contact", "time": "10:20"}, {"user": "user002", "page": "/home", "time": "10:25"} ] # 分析1: ユーザー別アクセス回数 user_access = {} for log in logs: user = log["user"] user_access[user] = user_access.get(user, 0) + 1 print("=== ユーザー別アクセス回数 ===") for user, count in sorted(user_access.items()): print(f"{user}: {count}回") # 分析2: ページ別アクセス回数 page_access = {} for log in logs: page = log["page"] page_access[page] = page_access.get(page, 0) + 1 print("\n=== ページ別アクセス回数 ===") for page, count in sorted(page_access.items(), key=lambda x: x[1], reverse=True): print(f"{page}: {count}回") # 分析3: 最もアクティブなユーザー most_active_user = max(user_access.items(), key=lambda x: x[1]) print(f"\n=== 最もアクティブなユーザー ===") print(f"{most_active_user[0]}: {most_active_user[1]}回") # 分析4: 最も人気のあるページ most_popular_page = max(page_access.items(), key=lambda x: x[1]) print(f"\n=== 最も人気のあるページ ===") print(f"{most_popular_page[0]}: {most_popular_page[1]}回") # 追加分析: ユーザーの行動パターン print("\n=== ユーザーの行動パターン ===") user_pages = {} for log in logs: user = log["user"] page = log["page"] if user not in user_pages: user_pages[user] = [] user_pages[user].append(page) for user, pages in user_pages.items(): print(f"{user}: {' → '.join(pages)}") # ユニークページ数 print("\n=== ユーザー別ユニークページ数 ===") for user, pages in user_pages.items(): unique_pages = len(set(pages)) print(f"{user}: {unique_pages}ページ")
実行結果:
=== ユーザー別アクセス回数 ===
user001: 3回
user002: 2回
user003: 1回
=== ページ別アクセス回数 ===
/home: 3回
/about: 1回
/products: 1回
/contact: 1回
=== 最もアクティブなユーザー ===
user001: 3回
=== 最も人気のあるページ ===
/home: 3回
=== ユーザーの行動パターン ===
user001: /home → /products → /contact
user002: /about → /home
user003: /home
=== ユーザー別ユニークページ数 ===
user001: 3ページ
user002: 2ページ
user003: 1ページ
6. 演習4: データのマージと変換
問題
複数のデータソースから情報を統合してください。
Python# ユーザー基本情報 users = { "user001": {"name": "太郎", "age": 25}, "user002": {"name": "花子", "age": 30}, "user003": {"name": "次郎", "age": 28} } # 購入履歴 purchases = [ {"user_id": "user001", "product": "book", "price": 1500}, {"user_id": "user001", "product": "pen", "price": 300}, {"user_id": "user002", "product": "book", "price": 1500}, {"user_id": "user003", "product": "notebook", "price": 500}, {"user_id": "user001", "product": "eraser", "price": 100} ] # 実装: # 1. ユーザーごとの購入総額を計算 # 2. ユーザー情報と購入情報を統合 # 3. 商品別の売上を集計
✅ 解答例
Pythonusers = { "user001": {"name": "太郎", "age": 25}, "user002": {"name": "花子", "age": 30}, "user003": {"name": "次郎", "age": 28} } purchases = [ {"user_id": "user001", "product": "book", "price": 1500}, {"user_id": "user001", "product": "pen", "price": 300}, {"user_id": "user002", "product": "book", "price": 1500}, {"user_id": "user003", "product": "notebook", "price": 500}, {"user_id": "user001", "product": "eraser", "price": 100} ] # 実装1: ユーザーごとの購入総額 user_totals = {} for purchase in purchases: user_id = purchase["user_id"] price = purchase["price"] user_totals[user_id] = user_totals.get(user_id, 0) + price print("=== ユーザー別購入総額 ===") for user_id, total in user_totals.items(): name = users[user_id]["name"] print(f"{name} ({user_id}): {total:,}円") # 実装2: 情報の統合 user_profiles = {} for user_id, info in users.items(): profile = info.copy() profile["user_id"] = user_id profile["total_spent"] = user_totals.get(user_id, 0) profile["purchase_count"] = 0 profile["products"] = [] user_profiles[user_id] = profile for purchase in purchases: user_id = purchase["user_id"] user_profiles[user_id]["purchase_count"] += 1 user_profiles[user_id]["products"].append(purchase["product"]) print("\n=== 統合ユーザープロフィール ===") for user_id, profile in user_profiles.items(): print(f"\n{profile['name']} ({user_id}):") print(f" 年齢: {profile['age']}歳") print(f" 購入回数: {profile['purchase_count']}回") print(f" 購入総額: {profile['total_spent']:,}円") print(f" 購入商品: {', '.join(profile['products'])}") # 実装3: 商品別売上 product_sales = {} for purchase in purchases: product = purchase["product"] price = purchase["price"] if product not in product_sales: product_sales[product] = {"count": 0, "total": 0} product_sales[product]["count"] += 1 product_sales[product]["total"] += price print("\n=== 商品別売上 ===") for product, data in sorted(product_sales.items(), key=lambda x: x[1]["total"], reverse=True): print(f"{product}: {data['count']}個, {data['total']:,}円") # 最高額購入者 top_buyer = max(user_totals.items(), key=lambda x: x[1]) print(f"\n=== 最高額購入者 ===") print(f"{users[top_buyer[0]]['name']}: {top_buyer[1]:,}円")
実行結果:
=== ユーザー別購入総額 ===
太郎 (user001): 1,900円
花子 (user002): 1,500円
次郎 (user003): 500円
=== 統合ユーザープロフィール ===
太郎 (user001):
年齢: 25歳
購入回数: 3回
購入総額: 1,900円
購入商品: book, pen, eraser
花子 (user002):
年齢: 30歳
購入回数: 1回
購入総額: 1,500円
購入商品: book
次郎 (user003):
年齢: 28歳
購入回数: 1回
購入総額: 500円
購入商品: notebook
=== 商品別売上 ===
book: 2個, 3,000円
pen: 1個, 300円
notebook: 1個, 500円
eraser: 1個, 100円
=== 最高額購入者 ===
太郎: 1,900円
7. 演習5: 設定管理システム
問題
階層的な設定データを管理するシステムを作成してください。
Python# デフォルト設定 default_config = { "app": { "name": "MyApp", "version": "1.0.0", "debug": False }, "database": { "host": "localhost", "port": 5432, "name": "mydb" }, "cache": { "enabled": True, "ttl": 3600 } } # ユーザー設定 user_config = { "app": { "debug": True }, "database": { "host": "prod-server" } } # 実装: # 1. 設定をマージする関数(ユーザー設定を優先) # 2. ドット記法で設定にアクセスする関数(例: "app.debug") # 3. 設定を検証する関数
✅ 解答例
Pythonimport copy default_config = { "app": { "name": "MyApp", "version": "1.0.0", "debug": False }, "database": { "host": "localhost", "port": 5432, "name": "mydb" }, "cache": { "enabled": True, "ttl": 3600 } } user_config = { "app": { "debug": True }, "database": { "host": "prod-server" } } # 機能1: 設定のマージ def merge_config(default, user): result = copy.deepcopy(default) for key, value in user.items(): if key in result and isinstance(result[key], dict) and isinstance(value, dict): result[key] = merge_config(result[key], value) else: result[key] = value return result # 機能2: ドット記法でアクセス def get_config_value(config, path): keys = path.split(".") value = config for key in keys: if isinstance(value, dict) and key in value: value = value[key] else: return None return value # 機能3: 設定の検証 def validate_config(config): errors = [] # 必須項目のチェック required = [ ("app.name", str), ("app.version", str), ("database.host", str), ("database.port", int), ("database.name", str) ] for path, expected_type in required: value = get_config_value(config, path) if value is None: errors.append(f"必須項目が不足: {path}") elif not isinstance(value, expected_type): errors.append(f"型エラー: {path} は {expected_type.__name__} 型である必要があります") return errors # 実行 final_config = merge_config(default_config, user_config) print("=== デフォルト設定 ===") for section, values in default_config.items(): print(f"{section}: {values}") print("\n=== ユーザー設定 ===") for section, values in user_config.items(): print(f"{section}: {values}") print("\n=== マージ後の設定 ===") for section, values in final_config.items(): print(f"{section}: {values}") print("\n=== ドット記法でアクセス ===") print(f"app.name: {get_config_value(final_config, 'app.name')}") print(f"app.debug: {get_config_value(final_config, 'app.debug')}") print(f"database.host: {get_config_value(final_config, 'database.host')}") print(f"database.port: {get_config_value(final_config, 'database.port')}") print(f"cache.ttl: {get_config_value(final_config, 'cache.ttl')}") print("\n=== 設定の検証 ===") errors = validate_config(final_config) if errors: print("エラーが見つかりました:") for error in errors: print(f" - {error}") else: print("設定は正常です")
実行結果:
=== デフォルト設定 ===
app: {'name': 'MyApp', 'version': '1.0.0', 'debug': False}
database: {'host': 'localhost', 'port': 5432, 'name': 'mydb'}
cache: {'enabled': True, 'ttl': 3600}
=== ユーザー設定 ===
app: {'debug': True}
database: {'host': 'prod-server'}
=== マージ後の設定 ===
app: {'name': 'MyApp', 'version': '1.0.0', 'debug': True}
database: {'host': 'prod-server', 'port': 5432, 'name': 'mydb'}
cache: {'enabled': True, 'ttl': 3600}
=== ドット記法でアクセス ===
app.name: MyApp
app.debug: True
database.host: prod-server
database.port: 5432
cache.ttl: 3600
=== 設定の検証 ===
設定は正常です
8. まとめ
このレッスンでは、辞書の基本操作を演習で統合して確認しました。
- 参照、更新、削除、メソッド、ループを組み合わせて実装できました。
- キーと値の扱いを明確にして処理を設計する力を確認しました。
- 要件に応じて辞書操作を選択する判断力を強化できました。
- 中間出力でデータ状態を確認するデバッグ手順を実践しました。
- 実務に近いデータ管理処理へ応用できる基礎を固めました。
Lesson6 / 6
演習:辞書の総合問題
目次
1. このレッスンで学ぶこと
- 辞書を使った実践的な演習
- データの集計と分析
- 複合的な問題の解決
- 実務に近いコーディング
2. なぜ演習が必要か?
辞書の操作を理解しただけでは、実際の問題解決には不十分です。
Python# 理論だけでは不十分 理論 = "辞書はキーと値のペア" # 実践で初めて理解が深まる 実践 = "データを効率的に管理・分析できる"
演習を通じて、辞書の実践力を身につけましょう。
💡 豆知識: 実務では、辞書はJSON APIのレスポンス処理、データベースレコードの表現、設定管理など、あらゆる場面で使われます。辞書を使いこなせることは、Pythonプログラマーにとって必須のスキルです。
3. 演習1: 在庫管理システム
問題
以下の商品在庫データを管理するシステムを作成してください。
Python# 商品在庫データ inventory = { "apple": {"price": 100, "stock": 50}, "banana": {"price": 80, "stock": 30}, "orange": {"price": 120, "stock": 20} } # 実装する機能: # 1. 商品を追加する関数 # 2. 在庫を更新する関数 # 3. 商品を削除する関数 # 4. 在庫切れ商品を確認する関数 # 5. 在庫総額を計算する関数
💡 ヒント
- 関数を使って機能を分ける
- 存在確認をしてからアクセス
- ループで全商品を処理
✅ 解答例
Pythoninventory = { "apple": {"price": 100, "stock": 50}, "banana": {"price": 80, "stock": 30}, "orange": {"price": 120, "stock": 20} } # 機能1: 商品を追加 def add_product(name, price, stock): if name in inventory: print(f"{name}は既に存在します") else: inventory[name] = {"price": price, "stock": stock} print(f"{name}を追加しました") # 機能2: 在庫を更新 def update_stock(name, quantity): if name in inventory: inventory[name]["stock"] += quantity new_stock = inventory[name]["stock"] print(f"{name}の在庫を更新: {new_stock}個") else: print(f"{name}が見つかりません") # 機能3: 商品を削除 def remove_product(name): if name in inventory: removed = inventory.pop(name) print(f"{name}を削除しました(価格: {removed['price']}円)") else: print(f"{name}が見つかりません") # 機能4: 在庫切れ確認 def check_out_of_stock(): out_of_stock = [] for name, info in inventory.items(): if info["stock"] == 0: out_of_stock.append(name) if out_of_stock: print(f"在庫切れ: {', '.join(out_of_stock)}") else: print("在庫切れ商品なし") return out_of_stock # 機能5: 在庫総額を計算 def calculate_total_value(): total = 0 for name, info in inventory.items(): value = info["price"] * info["stock"] total += value print(f"{name}: {info['price']}円 × {info['stock']}個 = {value:,}円") return total # テスト実行 print("=== 初期在庫 ===") for name, info in inventory.items(): print(f"{name}: {info['price']}円, 在庫{info['stock']}個") print("\n=== 商品追加 ===") add_product("grape", 200, 15) print("\n=== 在庫更新 ===") update_stock("apple", -10) update_stock("banana", 20) print("\n=== 在庫総額 ===") total = calculate_total_value() print(f"総額: {total:,}円") print("\n=== 在庫切れ確認 ===") check_out_of_stock() print("\n=== 商品削除 ===") remove_product("orange") print("\n=== 最終在庫 ===") for name, info in inventory.items(): print(f"{name}: {info['price']}円, 在庫{info['stock']}個")
実行結果:
=== 初期在庫 ===
apple: 100円, 在庫50個
banana: 80円, 在庫30個
orange: 120円, 在庫20個
=== 商品追加 ===
grapeを追加しました
=== 在庫更新 ===
appleの在庫を更新: 40個
bananaの在庫を更新: 50個
=== 在庫総額 ===
apple: 100円 × 40個 = 4,000円
banana: 80円 × 50個 = 4,000円
orange: 120円 × 20個 = 2,400円
grape: 200円 × 15個 = 3,000円
総額: 13,400円
=== 在庫切れ確認 ===
在庫切れ商品なし
=== 商品削除 ===
orangeを削除しました(価格: 120円)
=== 最終在庫 ===
apple: 100円, 在庫40個
banana: 80円, 在庫50個
grape: 200円, 在庫15個
4. 演習2: 成績管理システム
問題
生徒の成績データを管理し、以下の分析を行ってください。
Python# 生徒の成績データ students = { "太郎": {"math": 85, "english": 92, "science": 78}, "花子": {"math": 95, "english": 88, "science": 90}, "次郎": {"math": 72, "english": 85, "science": 80}, "三郎": {"math": 88, "english": 78, "science": 85} } # 実装する機能: # 1. 各生徒の平均点を計算 # 2. 科目別の平均点を計算 # 3. 最高点と最低点を持つ生徒を見つける # 4. 全科目80点以上の生徒を抽出
✅ 解答例
Pythonstudents = { "太郎": {"math": 85, "english": 92, "science": 78}, "花子": {"math": 95, "english": 88, "science": 90}, "次郎": {"math": 72, "english": 85, "science": 80}, "三郎": {"math": 88, "english": 78, "science": 85} } # 機能1: 各生徒の平均点 print("=== 生徒別平均点 ===") student_averages = {} for name, scores in students.items(): total = sum(scores.values()) average = total / len(scores) student_averages[name] = average print(f"{name}: {average:.2f}点") # 機能2: 科目別平均点 print("\n=== 科目別平均点 ===") subjects = ["math", "english", "science"] subject_averages = {} for subject in subjects: total = 0 count = 0 for scores in students.values(): total += scores[subject] count += 1 average = total / count subject_averages[subject] = average print(f"{subject}: {average:.2f}点") # 機能3: 最高点・最低点の生徒 print("\n=== 最高点・最低点 ===") max_student = max(student_averages.items(), key=lambda x: x[1]) min_student = min(student_averages.items(), key=lambda x: x[1]) print(f"最高平均: {max_student[0]} ({max_student[1]:.2f}点)") print(f"最低平均: {min_student[0]} ({min_student[1]:.2f}点)") # 機能4: 全科目80点以上 print("\n=== 全科目80点以上の生徒 ===") excellent_students = [] for name, scores in students.items(): if all(score >= 80 for score in scores.values()): excellent_students.append(name) print(f"{name}: {scores}") if not excellent_students: print("該当者なし") # 追加分析: 科目別最高得点者 print("\n=== 科目別最高得点者 ===") for subject in subjects: max_score = 0 top_student = "" for name, scores in students.items(): if scores[subject] > max_score: max_score = scores[subject] top_student = name print(f"{subject}: {top_student} ({max_score}点)") # 全体統計 all_scores = [] for scores in students.values(): all_scores.extend(scores.values()) print(f"\n=== 全体統計 ===") print(f"総合平均: {sum(all_scores) / len(all_scores):.2f}点") print(f"最高点: {max(all_scores)}点") print(f"最低点: {min(all_scores)}点")
実行結果:
=== 生徒別平均点 ===
太郎: 85.00点
花子: 91.00点
次郎: 79.00点
三郎: 83.67点
=== 科目別平均点 ===
math: 85.00点
english: 85.75点
science: 83.25点
=== 最高点・最低点 ===
最高平均: 花子 (91.00点)
最低平均: 次郎 (79.00点)
=== 全科目80点以上の生徒 ===
花子: {'math': 95, 'english': 88, 'science': 90}
=== 科目別最高得点者 ===
math: 花子 (95点)
english: 太郎 (92点)
science: 花子 (90点)
=== 全体統計 ===
総合平均: 84.67点
最高点: 95点
最低点: 72点
5. 演習3: アクセスログ分析
問題
Webサイトのアクセスログを分析してください。
Python# アクセスログデータ logs = [ {"user": "user001", "page": "/home", "time": "10:00"}, {"user": "user002", "page": "/about", "time": "10:05"}, {"user": "user001", "page": "/products", "time": "10:10"}, {"user": "user003", "page": "/home", "time": "10:15"}, {"user": "user001", "page": "/contact", "time": "10:20"}, {"user": "user002", "page": "/home", "time": "10:25"} ] # 分析内容: # 1. ユーザー別アクセス回数 # 2. ページ別アクセス回数 # 3. 最もアクティブなユーザー # 4. 最も人気のあるページ
✅ 解答例
Pythonlogs = [ {"user": "user001", "page": "/home", "time": "10:00"}, {"user": "user002", "page": "/about", "time": "10:05"}, {"user": "user001", "page": "/products", "time": "10:10"}, {"user": "user003", "page": "/home", "time": "10:15"}, {"user": "user001", "page": "/contact", "time": "10:20"}, {"user": "user002", "page": "/home", "time": "10:25"} ] # 分析1: ユーザー別アクセス回数 user_access = {} for log in logs: user = log["user"] user_access[user] = user_access.get(user, 0) + 1 print("=== ユーザー別アクセス回数 ===") for user, count in sorted(user_access.items()): print(f"{user}: {count}回") # 分析2: ページ別アクセス回数 page_access = {} for log in logs: page = log["page"] page_access[page] = page_access.get(page, 0) + 1 print("\n=== ページ別アクセス回数 ===") for page, count in sorted(page_access.items(), key=lambda x: x[1], reverse=True): print(f"{page}: {count}回") # 分析3: 最もアクティブなユーザー most_active_user = max(user_access.items(), key=lambda x: x[1]) print(f"\n=== 最もアクティブなユーザー ===") print(f"{most_active_user[0]}: {most_active_user[1]}回") # 分析4: 最も人気のあるページ most_popular_page = max(page_access.items(), key=lambda x: x[1]) print(f"\n=== 最も人気のあるページ ===") print(f"{most_popular_page[0]}: {most_popular_page[1]}回") # 追加分析: ユーザーの行動パターン print("\n=== ユーザーの行動パターン ===") user_pages = {} for log in logs: user = log["user"] page = log["page"] if user not in user_pages: user_pages[user] = [] user_pages[user].append(page) for user, pages in user_pages.items(): print(f"{user}: {' → '.join(pages)}") # ユニークページ数 print("\n=== ユーザー別ユニークページ数 ===") for user, pages in user_pages.items(): unique_pages = len(set(pages)) print(f"{user}: {unique_pages}ページ")
実行結果:
=== ユーザー別アクセス回数 ===
user001: 3回
user002: 2回
user003: 1回
=== ページ別アクセス回数 ===
/home: 3回
/about: 1回
/products: 1回
/contact: 1回
=== 最もアクティブなユーザー ===
user001: 3回
=== 最も人気のあるページ ===
/home: 3回
=== ユーザーの行動パターン ===
user001: /home → /products → /contact
user002: /about → /home
user003: /home
=== ユーザー別ユニークページ数 ===
user001: 3ページ
user002: 2ページ
user003: 1ページ
6. 演習4: データのマージと変換
問題
複数のデータソースから情報を統合してください。
Python# ユーザー基本情報 users = { "user001": {"name": "太郎", "age": 25}, "user002": {"name": "花子", "age": 30}, "user003": {"name": "次郎", "age": 28} } # 購入履歴 purchases = [ {"user_id": "user001", "product": "book", "price": 1500}, {"user_id": "user001", "product": "pen", "price": 300}, {"user_id": "user002", "product": "book", "price": 1500}, {"user_id": "user003", "product": "notebook", "price": 500}, {"user_id": "user001", "product": "eraser", "price": 100} ] # 実装: # 1. ユーザーごとの購入総額を計算 # 2. ユーザー情報と購入情報を統合 # 3. 商品別の売上を集計
✅ 解答例
Pythonusers = { "user001": {"name": "太郎", "age": 25}, "user002": {"name": "花子", "age": 30}, "user003": {"name": "次郎", "age": 28} } purchases = [ {"user_id": "user001", "product": "book", "price": 1500}, {"user_id": "user001", "product": "pen", "price": 300}, {"user_id": "user002", "product": "book", "price": 1500}, {"user_id": "user003", "product": "notebook", "price": 500}, {"user_id": "user001", "product": "eraser", "price": 100} ] # 実装1: ユーザーごとの購入総額 user_totals = {} for purchase in purchases: user_id = purchase["user_id"] price = purchase["price"] user_totals[user_id] = user_totals.get(user_id, 0) + price print("=== ユーザー別購入総額 ===") for user_id, total in user_totals.items(): name = users[user_id]["name"] print(f"{name} ({user_id}): {total:,}円") # 実装2: 情報の統合 user_profiles = {} for user_id, info in users.items(): profile = info.copy() profile["user_id"] = user_id profile["total_spent"] = user_totals.get(user_id, 0) profile["purchase_count"] = 0 profile["products"] = [] user_profiles[user_id] = profile for purchase in purchases: user_id = purchase["user_id"] user_profiles[user_id]["purchase_count"] += 1 user_profiles[user_id]["products"].append(purchase["product"]) print("\n=== 統合ユーザープロフィール ===") for user_id, profile in user_profiles.items(): print(f"\n{profile['name']} ({user_id}):") print(f" 年齢: {profile['age']}歳") print(f" 購入回数: {profile['purchase_count']}回") print(f" 購入総額: {profile['total_spent']:,}円") print(f" 購入商品: {', '.join(profile['products'])}") # 実装3: 商品別売上 product_sales = {} for purchase in purchases: product = purchase["product"] price = purchase["price"] if product not in product_sales: product_sales[product] = {"count": 0, "total": 0} product_sales[product]["count"] += 1 product_sales[product]["total"] += price print("\n=== 商品別売上 ===") for product, data in sorted(product_sales.items(), key=lambda x: x[1]["total"], reverse=True): print(f"{product}: {data['count']}個, {data['total']:,}円") # 最高額購入者 top_buyer = max(user_totals.items(), key=lambda x: x[1]) print(f"\n=== 最高額購入者 ===") print(f"{users[top_buyer[0]]['name']}: {top_buyer[1]:,}円")
実行結果:
=== ユーザー別購入総額 ===
太郎 (user001): 1,900円
花子 (user002): 1,500円
次郎 (user003): 500円
=== 統合ユーザープロフィール ===
太郎 (user001):
年齢: 25歳
購入回数: 3回
購入総額: 1,900円
購入商品: book, pen, eraser
花子 (user002):
年齢: 30歳
購入回数: 1回
購入総額: 1,500円
購入商品: book
次郎 (user003):
年齢: 28歳
購入回数: 1回
購入総額: 500円
購入商品: notebook
=== 商品別売上 ===
book: 2個, 3,000円
pen: 1個, 300円
notebook: 1個, 500円
eraser: 1個, 100円
=== 最高額購入者 ===
太郎: 1,900円
7. 演習5: 設定管理システム
問題
階層的な設定データを管理するシステムを作成してください。
Python# デフォルト設定 default_config = { "app": { "name": "MyApp", "version": "1.0.0", "debug": False }, "database": { "host": "localhost", "port": 5432, "name": "mydb" }, "cache": { "enabled": True, "ttl": 3600 } } # ユーザー設定 user_config = { "app": { "debug": True }, "database": { "host": "prod-server" } } # 実装: # 1. 設定をマージする関数(ユーザー設定を優先) # 2. ドット記法で設定にアクセスする関数(例: "app.debug") # 3. 設定を検証する関数
✅ 解答例
Pythonimport copy default_config = { "app": { "name": "MyApp", "version": "1.0.0", "debug": False }, "database": { "host": "localhost", "port": 5432, "name": "mydb" }, "cache": { "enabled": True, "ttl": 3600 } } user_config = { "app": { "debug": True }, "database": { "host": "prod-server" } } # 機能1: 設定のマージ def merge_config(default, user): result = copy.deepcopy(default) for key, value in user.items(): if key in result and isinstance(result[key], dict) and isinstance(value, dict): result[key] = merge_config(result[key], value) else: result[key] = value return result # 機能2: ドット記法でアクセス def get_config_value(config, path): keys = path.split(".") value = config for key in keys: if isinstance(value, dict) and key in value: value = value[key] else: return None return value # 機能3: 設定の検証 def validate_config(config): errors = [] # 必須項目のチェック required = [ ("app.name", str), ("app.version", str), ("database.host", str), ("database.port", int), ("database.name", str) ] for path, expected_type in required: value = get_config_value(config, path) if value is None: errors.append(f"必須項目が不足: {path}") elif not isinstance(value, expected_type): errors.append(f"型エラー: {path} は {expected_type.__name__} 型である必要があります") return errors # 実行 final_config = merge_config(default_config, user_config) print("=== デフォルト設定 ===") for section, values in default_config.items(): print(f"{section}: {values}") print("\n=== ユーザー設定 ===") for section, values in user_config.items(): print(f"{section}: {values}") print("\n=== マージ後の設定 ===") for section, values in final_config.items(): print(f"{section}: {values}") print("\n=== ドット記法でアクセス ===") print(f"app.name: {get_config_value(final_config, 'app.name')}") print(f"app.debug: {get_config_value(final_config, 'app.debug')}") print(f"database.host: {get_config_value(final_config, 'database.host')}") print(f"database.port: {get_config_value(final_config, 'database.port')}") print(f"cache.ttl: {get_config_value(final_config, 'cache.ttl')}") print("\n=== 設定の検証 ===") errors = validate_config(final_config) if errors: print("エラーが見つかりました:") for error in errors: print(f" - {error}") else: print("設定は正常です")
実行結果:
=== デフォルト設定 ===
app: {'name': 'MyApp', 'version': '1.0.0', 'debug': False}
database: {'host': 'localhost', 'port': 5432, 'name': 'mydb'}
cache: {'enabled': True, 'ttl': 3600}
=== ユーザー設定 ===
app: {'debug': True}
database: {'host': 'prod-server'}
=== マージ後の設定 ===
app: {'name': 'MyApp', 'version': '1.0.0', 'debug': True}
database: {'host': 'prod-server', 'port': 5432, 'name': 'mydb'}
cache: {'enabled': True, 'ttl': 3600}
=== ドット記法でアクセス ===
app.name: MyApp
app.debug: True
database.host: prod-server
database.port: 5432
cache.ttl: 3600
=== 設定の検証 ===
設定は正常です
8. まとめ
このレッスンでは、辞書の基本操作を演習で統合して確認しました。
- 参照、更新、削除、メソッド、ループを組み合わせて実装できました。
- キーと値の扱いを明確にして処理を設計する力を確認しました。
- 要件に応じて辞書操作を選択する判断力を強化できました。
- 中間出力でデータ状態を確認するデバッグ手順を実践しました。
- 実務に近いデータ管理処理へ応用できる基礎を固めました。