0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Python実践自作問題集】No.8 ネストされた辞書

0
Last updated at Posted at 2025-06-08

1. はじめに

この問題集は、Pythonの基礎を習得した後、次の段階へ進みたい人のサポートをすることが目的です。
また、競技プログラミングとは異なり、複雑なアルゴリズムの問題ではなく「可読性の最大化」に焦点を当てた問題が中心となります。

目次
前の問題:不正な値を許すな
次の問題:

2. 問題

"""
No.8 ネストされた辞書

次のように、keyが'.'区切りの文字列である辞書dictionaryが与えられます。
keyを'.'で分割し、ネストされた辞書を作成してください。
"""

from typing import Any

# 与えられる辞書の例(あくまで一例です)
dictionary: dict[str, Any] = {
    'food.fruit.apple': {'price': 150},
    'food.fruit': {'place': '1F'},
}

# 期待される結果
expected = {
    'food': {
        'fruit': {
            'apple': {'price': 150},
            'place': '1F',
        },
    },
}

3. 解答例

from dictknife import deepmerge
from nesteddict import NestedDict

nested = {}
for key, value in dictionary.items():
    nested = deepmerge(nested, NestedDict({key: value}))
1行で書く場合
from dictknife import deepmerge
from nesteddict import NestedDict

nested = deepmerge(*[NestedDict({key: value}) for key, value in dictionary.items()])

4. 採点基準

  • 「怠惰」になれましたか?

5. 解説

まさか、自力実装してしまいましたか?
という冗談は置いといて、今回は知っていると便利なライブラリ2選の紹介です。

初めにnesteddictライブラリですが、これはkeyが "." 区切りの辞書をネストされた辞書に変換してくれます。

from nesteddict import NestedDict


dictionary = {
    'food.fruit.apple': {'price': 150},
}
nested = NestedDict(dictionary)
print(nested)
実行結果
{'food': {'fruit': {'apple': {'price': 150}}}}

これだけで良いのでは?と思うかもしれませんが、実は落とし穴があります。
実際、例に挙げた辞書を変換すると期待通りになりません。

from nesteddict import NestedDict


dictionary = {
    'food.fruit.apple': {'price': 150},
    'food.fruit': {'place': '1F'},
}
nested = NestedDict(dictionary)
print(nested)
実行結果
{'food': {'fruit': {'place': '1F'}}}

'apple'以下のデータが消えてしまっていますね。
何が起きているのかというと、次の2つの辞書がマージされるときに2階層目以降のデータが上書きされてしまうのです。

key_1 = 'food.fruit.apple'
dictionary_1 = NestedDict({key_1: dictionary[key_1]})
print(f'{dictionary_1=}')

key_2 = 'food.fruit'
dictionary_2 = NestedDict({key_2: dictionary[key_2]})
print(f'{dictionary_2=}')

merged = dictionary_1 | dictionary_2
print(f'{merged=}')
実行結果
dictionary_1={'food': {'fruit': {'apple': {'price': 150}}}}
dictionary_2={'food': {'fruit': {'place': '1F'}}}
merged={'food': {'fruit': {'place': '1F'}}}

これを適切にマージするために、dictknifeライブラリのdeepmerge関数を使用します。

Pythonでネストしたdictをマージしたい - Qiita

dictknife,jsonknifeの機能を整理 - hatenablog.com

deep_merged = deepmerge(dictionary_1, dictionary_2)
print(f'{deep_merged=}')
実行結果
deep_merged={'food': {'fruit': {'apple': {'price': 150}, 'place': '1F'}}}

期待通りにマージされていますね。
これを繰り返すことで、目的のネストされた辞書が得られます。

どちらも有名なライブラリではないですが、知っていると時折活躍してくれます。
例えばiniファイルを読み込むとき、セクション名が "." 区切りだとこの問題と同じ状況になります。

Pythonでiniファイルを読み込むライブラリ「configparser」 - Qiita

6. テストコード

from dictknife import deepmerge
from nesteddict import NestedDict


nested = {}
for key, value in dictionary.items():
    nested = deepmerge(nested, NestedDict({key: value}))

print(nested)
assert nested == expected
実行結果
{'food': {'fruit': {'apple': {'price': 150}, 'place': '1F'}}}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?