Python | 1 日 120 分 × 7 日アプリ学習:辞書型で作るユーザー管理アプリ(中級編)

Web APP Python
スポンサーリンク

4日目のゴール

4日目のテーマは
「辞書型で管理しているユーザーを“探す・絞り込む”ことができるようになること」 です。

1〜3日目で、あなたはすでに CRUD(登録・一覧・更新・削除)を一通り体験しました。
今日はそこに、

ユーザーIDで1人だけ検索する
名前の一部であいまい検索する
検索結果をきれいに表示する

という「R(Read)の応用」を足していきます。


辞書から「1人だけ」を取り出す検索

ユーザーIDでピンポイントに探す

まずは一番シンプルな検索からいきます。
「ユーザーIDを入力して、そのユーザーだけ表示する」機能です。

辞書の構造はこうでした。

users = {
    "u001": {"id": "u001", "name": "Taro", "age": 25, "email": "taro@example.com"},
    "u002": {"id": "u002", "name": "Hanako", "age": 30, "email": "hanako@example.com"}
}
Python

このとき、ID からユーザーを取り出すのはこうでした。

user = users["u001"]
Python

これを「アプリの機能」として形にすると、こうなります。

def find_user_by_id(users):
    print("=== ユーザー検索(ID指定) ===")
    user_id = input("検索したいユーザーID: ").strip()

    if user_id not in users:
        print("そのIDのユーザーは存在しません。")
        return

    user = users[user_id]
    print("=== 検索結果 ===")
    print(f"ID: {user['id']}")
    print(f"名前: {user['name']}")
    print(f"年齢: {user['age']}")
    print(f"メール: {user['email']}")
Python

ここでの重要ポイントは、
「存在チェックをしてから取り出す」 ことです。

user_id not in users を先に確認しておくことで、
users[user_id] で KeyError を起こさずに済みます。


「一覧」と「検索」の違いを言葉で整理する

Read には二つの顔がある

ここまでで、Read(読み取り)は二種類出てきました。

全員を表示する「一覧表示」
特定の1人だけを表示する「検索」

どちらも「読む」ですが、
やっていることは少し違います。

一覧表示は、
「全員をぐるっと回して、全員分を表示する」。

検索は、
「条件に合うユーザーだけを取り出して表示する」。

この「条件」という考え方が、
今日のキーワードです。


名前の一部で検索する(あいまい検索)

「部分一致」で探すという発想

現実のアプリでは、
「ID は覚えてないけど、名前に ‘太郎’ が入ってたはず」
みたいな探し方をしたくなります。

そこで、
「名前にキーワードが含まれているユーザーだけを表示する」
という機能を作ります。

def find_users_by_name(users):
    print("=== ユーザー検索(名前の一部) ===")
    keyword = input("名前に含まれる文字を入力してください: ").strip()

    if keyword == "":
        print("キーワードが空です。検索を中止します。")
        return

    keyword_lower = keyword.lower()
    found = False

    for user_id, user in users.items():
        name_lower = user["name"].lower()

        if keyword_lower in name_lower:
            if not found:
                print("=== 検索結果 ===")
            found = True
            print(f"- ID: {user['id']}")
            print(f"  名前: {user['name']}")
            print(f"  年齢: {user['age']}")
            print(f"  メール: {user['email']}")
            print("----------")

    if not found:
        print(f"「{keyword}」を含む名前のユーザーは見つかりませんでした。")
Python

ここで深掘りしたいポイントは、いくつかあります。

users.items() で「ID とユーザー辞書」を同時に取り出している
keyword_lower in name_lower で「部分一致」を判定している
大文字・小文字の違いを無視するために、両方 lower() にしている
found フラグで「1件もヒットしなかった場合」を判定している

つまり、
「辞書をぐるっと回しながら、条件に合うものだけを拾う」
というパターンを使っています。


検索結果の表示を共通化する

「表示の仕方」を関数にしておくと楽になる

ID 検索でも名前検索でも、
ユーザー情報の表示の仕方はほとんど同じですよね。

こういうときは、
「表示だけを担当する関数」を作っておくとスッキリします。

def print_user(user):
    print(f"ID: {user['id']}")
    print(f"名前: {user['name']}")
    print(f"年齢: {user['age']}")
    print(f"メール: {user['email']}")
Python

これを使うと、
さっきの ID 検索はこう書き換えられます。

def find_user_by_id(users):
    print("=== ユーザー検索(ID指定) ===")
    user_id = input("検索したいユーザーID: ").strip()

    if user_id not in users:
        print("そのIDのユーザーは存在しません。")
        return

    user = users[user_id]
    print("=== 検索結果 ===")
    print_user(user)
Python

名前検索も、こう書けます。

def find_users_by_name(users):
    print("=== ユーザー検索(名前の一部) ===")
    keyword = input("名前に含まれる文字を入力してください: ").strip()

    if keyword == "":
        print("キーワードが空です。検索を中止します。")
        return

    keyword_lower = keyword.lower()
    found = False

    for user_id, user in users.items():
        name_lower = user["name"].lower()

        if keyword_lower in name_lower:
            if not found:
                print("=== 検索結果 ===")
            found = True
            print_user(user)
            print("----------")

    if not found:
        print(f"「{keyword}」を含む名前のユーザーは見つかりませんでした。")
Python

ここでの重要ポイントは、
「同じことを何度も書かない」 という意識です。

表示ロジックを1か所にまとめておくと、
あとで表示形式を変えたくなったときも、
その関数だけ直せば済みます。


4日目版メニュー:検索機能を組み込む

3日目までの CRUD に「検索」を足す

これまでの CRUD メニューに、
検索メニューを追加してみます。

def show_menu():
    print("==========")
    print("ユーザー管理アプリ(4日目)")
    print("1: ユーザーを登録する(Create)")
    print("2: ユーザー一覧を表示する(Read)")
    print("3: ユーザー情報を更新する(Update)")
    print("4: ユーザーを削除する(Delete)")
    print("5: ユーザーをIDで検索する")
    print("6: ユーザーを名前の一部で検索する")
    print("0: 終了")
    print("==========")
Python

main はこうなります。

def main():
    users = {}

    while True:
        show_menu()
        choice = input("番号を選んでください: ").strip()

        if choice == "1":
            add_user(users)
        elif choice == "2":
            show_all_users(users)
        elif choice == "3":
            update_user(users)
        elif choice == "4":
            delete_user(users)
        elif choice == "5":
            find_user_by_id(users)
        elif choice == "6":
            find_users_by_name(users)
        elif choice == "0":
            print("アプリを終了します。")
            break
        else:
            print("不正な入力です。0〜6 のどれかを選んでください。")
Python

これで、
「登録・一覧・更新・削除・検索」
という、かなり実用的なユーザー管理アプリの形になってきます。


4日目の完成コード(要点部分)

検索まわりを中心にした全体像

CRUD 部分は3日目と同じなので、
ここでは「検索」と「表示」の部分を中心に載せます。

def print_user(user):
    print(f"ID: {user['id']}")
    print(f"名前: {user['name']}")
    print(f"年齢: {user['age']}")
    print(f"メール: {user['email']}")


def find_user_by_id(users):
    print("=== ユーザー検索(ID指定) ===")
    user_id = input("検索したいユーザーID: ").strip()

    if user_id not in users:
        print("そのIDのユーザーは存在しません。")
        return

    user = users[user_id]
    print("=== 検索結果 ===")
    print_user(user)


def find_users_by_name(users):
    print("=== ユーザー検索(名前の一部) ===")
    keyword = input("名前に含まれる文字を入力してください: ").strip()

    if keyword == "":
        print("キーワードが空です。検索を中止します。")
        return

    keyword_lower = keyword.lower()
    found = False

    for user_id, user in users.items():
        name_lower = user["name"].lower()

        if keyword_lower in name_lower:
            if not found:
                print("=== 検索結果 ===")
            found = True
            print_user(user)
            print("----------")

    if not found:
        print(f"「{keyword}」を含む名前のユーザーは見つかりませんでした。")
Python

この3つの関数だけでも、
「辞書を使った検索の基本パターン」がぎゅっと詰まっています。


「検索」を自分の言葉で説明してみる

ここまで来たあなたなら、こう言えるはず

ID 検索
「ユーザーIDを入力してもらい、そのIDが users 辞書にあれば、そのユーザーだけを表示する。」

名前検索
「users 辞書をぐるっと回しながら、名前にキーワードを含むユーザーだけを拾って表示する。
大文字・小文字の違いは無視する。」

print_user
「1人のユーザー辞書を、決まったフォーマットで表示する。」

ここまで自分の言葉で説明できれば、
「辞書型+条件+ループで“探す”」 という感覚は、もうあなたのものです。


4日目のまとめ:今日つかんでほしい感覚

今日の本質は、これです。

Read(読み取り)は「全部表示」だけではなく、「条件に合うものだけ表示」も含んでいる。
辞書の検索は、「キーで一発」と「値の中身を見ながら絞り込む」の二種類がある。
inlower() を組み合わせると、あいまい検索(部分一致・大文字小文字無視)が簡単に書ける。
表示ロジックを関数にまとめると、コードが読みやすくなり、変更にも強くなる。

ここまで来たあなたなら、
5日目以降の「並び替え(ソート)」「条件を組み合わせた絞り込み」「ファイル保存」といった
“アプリとしての完成度を上げるステップ”にも、自然に進んでいけます。

タイトルとURLをコピーしました