juno_rmks
@juno_rmks (ゆの)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

より Pythonic なコーディングがあればご教授ください。

解決したいこと

既に存在している dict[str, tuple[Union(str, None), Union(str, None), Union(str, None)]] 型からキーと値が逆転した新しい dict[str, str] 型を作成しているのですが、より Pythonic な書き方があれば、ご教授いただきたいです。

ここで開発中です。

現在のコード

half_to_full_letter_map = {
    '\uFF71': ('\u30A2', None, None),  # ア
    '\uFF72': ('\u30A4', None, None),  # イ
    '\uFF73': ('\u30A6', '\u30F4', None),  # ウ
    '\uFF74': ('\u30A8', None, None),  # エ
    '\uFF75': ('\u30AA', None, None),  # オ
    # 中略
    '\uFF8A': ('\u30CF', '\u30D0', '\u30D1'),  # ハ
    '\uFF8B': ('\u30D2', '\u30D3', '\u30D4'),  # ヒ
    '\uFF8C': ('\u30D5', '\u30D6', '\u30D7'),  # フ
    '\uFF8D': ('\u30D8', '\u30D9', '\u30DA'),  # ヘ
    '\uFF8E': ('\u30DB', '\u30DC', '\u30DD'),  # ホ
    # 省略
}

full_to_half_letter_map = {
    **{v[0]: k for k, v in half_to_full_letter_map.items() if v[0] is not None},
    **{v[1]: f'{k}\uFF9E' for k, v in half_to_full_letter_map.items() if v[1] is not None},
    **{v[2]: f'{k}\uFF9F' for k, v in half_to_full_letter_map.items() if v[2] is not None},
}

half_to_full_letter_map は、半角カタカナをキー、その半角カタカナの全角での清音、濁音、半濁音をタプルとして値に持っています。対応する清音、濁音、半濁音がない場合は、None を値として持ちます。

full_to_half_letter_map は、half_to_full_letter_map の値であったタプル内の清音、濁音、半濁音をそれぞれキーとし、キーであった半角カタカナを値として持つ dict です。

自分で試したこと

取り敢えず、内包表記で清音、濁音、半濁音をそれぞれ取り出し、展開して full_to_half_letter_map を作りましたが、関数型プログラミング用モジュールといったあたりを使用してもっと Pythonic に書けるのでは、と考えています。

0

2Answer

1行にしてみました。主旨と違う?

voicing_mark = ['', '\uFF9E', '\uFF9F']
full_to_half_letter_map = { v[n]: f'{k}{voicing_mark[n]}' for k, v in half_to_full_letter_map.items() for n in range(len(voicing_mark)) if v[n] is not None }

あと、自分はdictの連結に|演算子を使います(Python3.9以降)。好みの問題ですね。

full_to_half_letter_map = \
{v[0]: k for k, v in half_to_full_letter_map.items() if v[0] is not None} | \
{v[1]: f'{k}\uFF9E' for k, v in half_to_full_letter_map.items() if v[1] is not None} | \
{v[2]: f'{k}\uFF9F' for k, v in half_to_full_letter_map.items() if v[2] is not None}
1Like

Comments

  1. @juno_rmks

    Questioner

    ありがとうございます。
    voicing_mark でループさせて、1行にするのは、思いつかなかったです。
    主旨に沿ってます。
    自分だけでコーディングしていると決まった形になりがちで、自分が思いつかない発想、角度のコーディングに触れたいな、と思っていたので、とても面白いです!

    > dictの連結に|演算子

    確かに、それもできますね。このプロダクトは、最小バージョン 3.7 に設定しているので、採用していませんが、パイプはありですね。

    2つも刺激的な回答をくださり、改めてありがとうございますm(_ _)m
  2. お役立てて何よりです。用済みであればクローズしてください。

@nak435 さんのコードのrangeをzipにしてみました。

voicing_mark = ('', '\uFF9E', '\uFF9F')
full_to_half_letter_map = {
    u: k + m
    for k, v in half_to_full_letter_map.items()
    for u, m in zip(v, voicing_mark)
    if u is not None
}

half_to_full_letter_map にNoneを書かなければもっと楽に処理できそうですね。

0Like

Your answer might help someone💌