Превращаем вложенный словарь в плоский. Неправильный вывод
Задача
Превращаем вложенный словарь в плоский
Перед вами имеется вложенный словарь, уровень вложенности произвольный и заранее неизвестен. Ключами словаря на любом уровне могут быть только строки, значения - только числа.
Учитывая указанные выше условия, ваша задача состоит в том, чтобы преобразовать этот вложенный словарь в плоский (состоящий только из одного уровня), где ключи формируются конкатенацией вложенных ключей, соединенных знаком: _
Для этого необходимо определить рекурсивную функцию flatten_dict. Она должна принимать вложенный словарь и возвращать плоский
Ниже приведены несколько способов решения вышеуказанной задачи.
nested = {'Germany': {'berlin': 7},
'Europe': {'italy': {'Rome': 3}},
'USA': {'washington': 1, 'New York': 4}}
flatten_dict(nested) => {'Germany_berlin': 7,
'Europe_italy_Rome': 3,
'USA_washington': 1,
'USA_New York': 4}
nested = {'Q': {'w': {'E': {'r': {'T': {'y': 123}}}}}}
flatten_dict(nested) => {'Q_w_E_r_T_y': 123}
Мой код
def flatten_dict(user_dict: dict[any, any], total_dict: dict[any, any] = {}, x: [str] = [], y: [int] = []) -> dict:
for key, value in user_dict.items():
if type(value) == dict:
x.append(key)
flatten_dict(user_dict[key], total_dict, x, y)
else:
x.append(key)
y.append(value)
if type(value) != dict:
total_dict['_'.join(x)] = y[0]
x.clear()
y.clear()
return total_dict
Проблема
Код работает, но при наличии более, так скажем, одной цифры в ряду словарей, выводит неправильно. Пример:
ввожу:
flatten_dict({'Germany':7,'Europe': {'italy': {'Rome': 3}},'USA': {'washington': 1, 'New York': 4}}))
выводит:
{'Germany': 7, 'Europe_italy_Rome': 3, 'USA_washington': 1, 'New York': 4}
Ответы (2 шт):
def flatten(nested_dict={}, flatten_dict={}):
for key, value in nested_dict.items():
if isinstance(value, dict):
flatten({f'{key}_{sub_key}': sub_value for sub_key, sub_value in value.items()}, flatten_dict)
else:
flatten_dict[key] = value
return flatten_dict
nested = {'Germany':7,'Europe': {'italy': {'Rome': 3}},'USA': {'washington': 1, 'New York': 4}}
print(flatten(nested))
# {'Germany': 7, 'Europe_italy_Rome': 3, 'USA_washington': 1, 'USA_New York': 4}
Я бы немного модернизировал предыдущий код что бы сделать разные словари при вызове функции так как при запуске нескольких проверок накапливается в один и тот же словарь
def flatten_dict(nested_dict={}, flatten=None):
if flatten is None:
flatten = {}
for key, value in nested_dict.items():
if isinstance(value, dict):
flatten_dict({f'{key}_{sub_key}': sub_value for sub_key,
sub_value in value.items()}, flatten)
else:
flatten[key] = value
return flatten
assert flatten_dict({'Q': {'w': {'E': {'r': {'T': {'y': 123}}}}}}) == {
'Q_w_E_r_T_y': 123}
assert flatten_dict({'Germany_berlin': 7,
'Europe_italy_Rome': 3,
'USA_washington': 1,
'USA_New York': 4}) == {'Germany_berlin': 7, 'Europe_italy_Rome': 3, 'USA_washington': 1,
'USA_New York': 4}
assert flatten_dict({'a': 100, 'b': 200}) == {'a': 100, 'b': 200}
assert flatten_dict(
{'Geeks': {'for': {'for': 1, 'geeks': 4}}, 'for': {'geeks': {'Geeks': 3}}, 'geeks': {'Geeks': {'for': 7}}}) == {
'Geeks_for_geeks': 4, 'for_geeks_Geeks': 3, 'geeks_Geeks_for': 7, 'Geeks_for_for': 1}
assert flatten_dict({"a": 1,
"b": {
"c": 2,
"d": 3,
"e": {
"f": 4,
'6': 100,
'5': {"g": 6},
"l": 1,
}
}}) == {'a': 1, 'b_c': 2, 'b_d': 3, 'b_e_f': 4, 'b_e_6': 100, 'b_e_5_g': 6, 'b_e_l': 1}