見出し画像

YAMLのいじり方(2)


はじめに:Gemini Code Assistすごいね

 私自身まだ、Gemini Code Assist(以下「GCA」)を使い始めて一週間にもなっていませんが、断言します。GCAを使うことはPython初心者・学習者にとって、ぶっこわれ「チートスキル」を手に入れたようなものだ!!!

 自身、最初に試したのが2月26日でした。

ちょうどネット記事にも紹介されていました。

 データの構成や処理方法を指示するだけで、コードを書いてくれる。適切にコメントも入っていて、整理された、とても分かりやすいコードが出力される。「自分のやりたいこと」を通して「自分の勉強」になる。すごい。

今回やってみること・・データ構造定義

さて前回の

・・・では、「繁体字中文の単語カード」という想定で作業を進め、キー名などを決めました。
 しかし、今後、中学生が英単語や歴史の年表、元素記号など、様々な科目の暗記に使えるように、汎用的なフラッシュカードアプリにしたいと考えています。そのためゼロからデータ設計を見直すことにしました。

 まず、YAMLデータ構造定義の仕様指示はどうしたらよいか聞いたら、こんな回答でした。(この指示構成は今後も活用できると思います。)

GeminiにYAMLデータ構造を生成してもらうためには、以下の点を明確に整理し、Geminiに伝えることが重要です。具体的に整理すべき仕様を段階的に説明します。

1. 全体の概要・目的の明確化:
・何のデータ構造なのか?:
まずは、作成したいYAMLデータ構造が何を表すのかを明確にしましょう。例えば、「ユーザー情報」「設定ファイル」「商品情報」「タスクリスト」など、大まかな目的や内容を伝えましょう。
データの利用目的は?: そのYAMLデータがどのように使われるのか、利用目的も明確にすると、より適切な構造を生成できます。例えば、「アプリケーションの設定を読み込む」「APIのレスポンスとして返す」「データ分析に使う」などです。

2. データ構造の詳細の定義:
・キーと値の関係:

YAMLはキーと値のペアで構成されます。どのようなキーが必要で、それぞれのキーにどのような値を格納するのかを定義します。
・・キー名: 各キーの名前を決定します。わかりやすく、一貫性のある名前を使いましょう。例:name, email, age
・・値のデータ型: 各キーに格納される値のデータ型を明確にします。
・・・文字列 (string): テキストデータ ("example", "Hello World")
・・・数値 (integer, float): 整数や浮動小数点数 (10, 3.14)
・・・真偽値 (boolean): 真 (true) または偽 (false)
・・・リスト (list/array): 複数の値の順序付きリスト ([1, 2, 3], ["apple", "banana"])
・・・マップ/辞書 (map/dictionary): キーと値のペアを複数持つデータ構造 ({name: "John", age: 30})
・・・null: 値がない場合 (null)
・・キーの必須/任意:キーが必須かどうかを明確化します。

構造の階層化: データ構造が複雑な場合、どのように階層化するのかを決めます。
・・ネスト(入れ子): マップやリストの中に、さらにマップやリストを入れることで階層構造を作ります。例:user: {name: "John", address: {city: "Tokyo", country: "Japan"}}
リストの表現:リストの要素がどの様な構造を持つかを記述します。

3. データ例の提供 (任意ですが強力):
・具体的なデータ例:
可能であれば、想定されるデータ例をいくつか提供すると、Geminiはより正確なYAML構造を生成できます。例を示すことで、データ型や構造の理解を深めることができます。


4. 追加の制約や要件:特定のフォーマット:
・特定のフォーマット(例えば、ISO 8601形式の日付)を使用したい場合は、それを明記します。
値の制約: 値に制約がある場合(例えば、年齢は0以上120以下)は、それを伝えます。
コメントの追加:生成されたYAMLファイルにどの様なコメントを入れて欲しいかを指定します。

Geminiへの指示の例:
上記の仕様をGeminiに伝える際の指示の例です。

Gemini回答
以下の仕様に基づいて、YAMLデータ構造を生成してください。

## 仕様

### 概要
- ユーザー情報を管理するためのデータ構造を作成します。
- ユーザーID、名前、メールアドレス、年齢、住所を格納します。
- 住所には、都道府県、市区町村、番地を入れます。

### キーと値
- user_id: ユーザーID (整数、必須)
- name: ユーザー名 (文字列、必須)
- email: メールアドレス (文字列、必須)
- age: 年齢 (整数、任意、0以上120以下)
- address: 住所 (マップ、必須)
    - prefecture: 都道府県 (文字列、必須)
    - city: 市区町村 (文字列、必須)
    - street: 番地 (文字列、必須)

### データ例
以下のようなデータが格納されることを想定しています。

- ユーザーID: 1, 名前: 山田太郎, メール: taro.yamada@example.com, 年齢: 30, 住所: 東京都, 新宿区, 1-1-1
- ユーザーID: 2, 名前: 田中花子, メール: hanako.tanaka@example.com, 住所: 大阪府, 大阪市, 2-2-2

### 追加要件
- 生成されたYAMLに各キーの意味をコメントとして追加して下さい。

###出力形式
生成されたYAMLデータ構造を出力して下さい。

このプロンプトの構成は応用がききそうです。

フラッシュカードのデータ設計

では上の例を参考に、自分なりに「フラッシュカード」データの仕様を書いてみます。

自作の仕様書

以下の仕様に基づいて、YAMLデータ構造を生成してください。

## 仕様

### 概要
- 出題に対応した解答を暗記するための「フラッシュカード」のデータ構造を作成します。
- カード表の出題文字列、カード裏の解答文字列、暗記定着度、最終学習日時を格納します。

### キーと値
- front: カード表の出題文字列 (文字列、必須)
- back: カード裏の解答文字列 (文字列、必須)
- retention_rate: 暗記定着度 (整数、任意、0以上5以下)
- learned_datetime: 最終学習日時(日時、任意)

### データ例
以下のようなデータが格納されることを想定しています。

- 表: 獨居, 裏:一人暮らし, 暗記定着度: 1, learned_datetime: '2025-03-04 18:39:58'
- 表: 長輩, 裏:年長者, 
- 表: 聚餐, 裏:会食, 暗記定着度: 2, learned_datetime: '2025-03-03 23:19:14'
- 表: 圍爐, 裏:囲炉裏を囲む, 

### 追加要件
- 生成されたYAMLに各キーの意味をコメントとして追加して下さい。

###出力形式
生成されたYAMLデータ構造を出力して下さい。

Gemini回答

以下、ご提示いただいた仕様に基づき生成したYAMLデータ構造です。

# フラッシュカードのデータ構造
cards:
  - # カード1枚目
    front: 獨居 # カード表の出題文字列
    back: 一人暮らし # カード裏の解答文字列
    retention_rate: 1 # 暗記定着度 (0〜5の整数)
    learned_datetime: '2025-03-04 18:39:58' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
  - # カード2枚目
    front: 長輩 # カード表の出題文字列
    back: 年長者 # カード裏の解答文字列
    retention_rate: null # 暗記定着度 (0〜5の整数) 未設定時はnull
    learned_datetime: null # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式) 未設定時はnull
  - # カード3枚目
    front: 聚餐 # カード表の出題文字列
    back: 会食 # カード裏の解答文字列
    retention_rate: 2 # 暗記定着度 (0〜5の整数)
    learned_datetime: '2025-03-03 23:19:14' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
  - # カード4枚目
    front: 圍爐 # カード表の出題文字列
    back: 囲炉裏を囲む # カード裏の解答文字列
    retention_rate: null # 暗記定着度 (0〜5の整数) 未設定時はnull
    learned_datetime: null # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式) 未設定時はnull

解説:

  • cards::このキーは、フラッシュカードのリストを表します。

  • -:ハイフンはYAMLにおけるリストの要素を表します。つまり、-で始まる各ブロックが1枚のフラッシュカードを表しています。

  • front:カードの表側(問題)の文字列です。

  • back:カードの裏側(解答)の文字列です。

  • retention_rate:暗記定着度です。データ例では0〜5の整数が想定されているため、そのように設定できます。また、任意とあったため、未設定のカードにはnullを設定しています。

  • learned_datetime:最終学習日時です。データ例ではYYYY-MM-DD HH:MM:SS形式が想定されているため、そのように設定しています。また、任意とあったため、未設定のカードにはnullを設定しています。

  • コメント: #を使用して行末に追記しています。

  • null: 未設定を表現する為にnullを使用しています。

補足:

  • データ例では retention_rate と learned_datetime が未設定の場合もありましたが、YAMLでは値を省略することができないため、明示的に null を設定しています。これにより、値が「未設定」であることを明確に表現できます。

  • データはリスト構造を取っているので、いくらでも追加する事ができます。

以上が、ご指示に基づいて生成したYAMLデータ構造です。他に修正点や追加のご要望があればお気軽にお申し付けください。

再質問

>データ例では retention_rate と learned_datetime が未設定の場合もありましたが、YAMLでは値を省略することができないため、明示的に null を設定しています。これにより、値が「未設定」であることを明確に表現できます。

とのことですが、以前Geminiから

>learned: true なら「覚えた」、learned: false なら「まだ覚えていない」とします。 または、learned: true があれば「覚えた」、このキーがなければ、「まだ覚えていない」としてもよいです。

と教わりました。最初からretention_rate と learned_datetimeをいちいちnull設定するのも無駄な気がするので、キーが無ければnullという扱いにしたいと思うのですが?

Gemini再回答

承知いたしました。過去のやり取りもコンテキストとして一旦クリアにします。今回の「retention_rate と learned_datetime のキーがない場合は null と解釈したい」というご要望を最優先として理解しました。

つまり、以下の要件でYAMLデータ構造を生成したいということですね。

要件の再確認

  • キーがない場合、nullとみなす: retention_rate や learned_datetime のキー自体が存在しない場合は、その値がnull(未設定)であると解釈する。

  • キーがある場合のみ、値を入れる: retention_rate や learned_datetime のキーが存在する場合は、そこに設定された値を使用する。

  • それ以外のキーは前回の指定の通り

修正されたYAMLの例

上記を踏まえて、修正したYAMLのデータ構造を以下に示します。

content_copyaddcompare_arrowsopen_in_full# フラッシュカードのデータ構造
cards:
  - # カード1枚目
    front: 獨居 # カード表の出題文字列
    back: 一人暮らし # カード裏の解答文字列
    retention_rate: 1 # 暗記定着度 (0〜5の整数)
    learned_datetime: '2025-03-04 18:39:58' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
  - # カード2枚目
    front: 長輩 # カード表の出題文字列
    back: 年長者 # カード裏の解答文字列
  - # カード3枚目
    front: 聚餐 # カード表の出題文字列
    back: 会食 # カード裏の解答文字列
    retention_rate: 2 # 暗記定着度 (0〜5の整数)
    learned_datetime: '2025-03-03 23:19:14' # 最終学習日時 (YYYY-MM-DD HH:MM:SS形式)
  - # カード4枚目
    front: 圍爐 # カード表の出題文字列
    back: 囲炉裏を囲む # カード裏の解答文字列

解説

  • カード2枚目と4枚目からキーが削除: retention_rate と learned_datetime のキーがカード2枚目と4枚目から完全に削除されています。これにより、これらのカードの暗記定着度と最終学習日時は「未設定」(つまりnull)であることを表現します。

  • カード1と3枚目:前回指定通りデータが存在しています。

  • カード2枚目と4枚目は暗記定着度と最終学習日時が未設定: データが無い事を意味します。

  • コメント:前回指定通りです。

メリット

  • データ量の削減: 不必要な null の設定が不要となり、データサイズが小さくなります。

  • 可読性の向上: データが明確に設定されているキーのみに注目できるため、可読性が向上します。

  • 効率的な処理: YAMLを読み込むアプリケーション側で「キーが存在しない場合はnullである」というルールで処理することで、効率的なデータ処理が可能になります。

アプリケーション側の実装

このYAMLを読み込むアプリケーション側では、以下のロジックで処理することになります。

  1. retention_rate キーが存在するかチェックする。

  2. 存在すればその値を使い、存在しなければnull(未設定)とみなす。

  3. learned_datetime キーも同様に、存在するかをチェックし、存在すればその値を使い、存在しなければnull(未設定)とみなす。

まとめ

これで、ご要望通りの「キーが存在しなければnullとみなす」というYAMLデータ構造が完成しました。より効率的で可読性の高いデータ構造になったと思います。

他に修正点や追加のご要望がありましたら、お気軽にお申し付けください。

今回のデータ構造を導く仕様書

今回のデータ構造を導くのに必要十分な仕様書もGemini自身に出力してもらいました。

以下の仕様に基づいて、YAMLデータ構造を生成してください。

### 仕様

- フラッシュカードのデータ構造を作成します。
- 各カードは、表側の出題文字列 (`front`)、裏側の解答文字列 (`back`)、暗記定着度 (`retention_rate`)、最終学習日時 (`learned_datetime`) を持ちます。
- `front``back` は必須の文字列です。
- `retention_rate`0から5までの整数で、任意です。キーが存在しない場合、未設定(null)とみなします。
- `learned_datetime` は日時で、任意です。キーが存在しない場合、未設定(null)とみなします。
- データはリスト構造にしてください。
- 各キーの意味をコメントで追記して下さい。

### データ例
以下のようなデータが格納されることを想定しています。

- 表: 獨居, 裏:一人暮らし, 暗記定着度: 1, learned_datetime: '2025-03-04 18:39:58'
- 表: 長輩, 裏:年長者
- 表: 聚餐, 裏:会食, 暗記定着度: 2, learned_datetime: '2025-03-03 23:19:14'
- 表: 圍爐, 裏:囲炉裏を囲む

###出力形式
生成されたYAMLデータ構造を出力して下さい。

感想

いい感じで作ってくれました。
これまでのように自分一人で考えるのだったら、ここに至るまで何日かかることでしょうか?


いいなと思ったら応援しよう!