Функция от python, которая изменяет тип ключа в словаре
Имеется двух-уровневый словарь со строковыми ключами:
{'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6]}}
Я написал свой обработчик, который преобразует ключи в целочисленные:
def test(dict_in):
cash_ = {}
for key, val in dict_in.items():
key = int(key)
if isinstance(val, dict):
cash_[key] = test(val)
else:
cash_[key] = val
return cash_
Итог работы:
{3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6]}}
Собственно сам вопрос: есть ли стандартная функция от Python, которая делает тоже самое?
Ответы (4 шт):
думаю, что такой специальной функции нет. но для больших данных для двухуровневого словаря можно попробовать повысить эффективность с помощью pandas, например.
import pandas as pd
d = {'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6]}}
df = pd.DataFrame(d)
df.index = df.index.astype(int)
df.columns = df.columns.astype(int)
res = df.to_dict()
res:
{3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6]}}
разумеется, здесь не проводится проверка на исключения.
Не могу подвергать сомнению решение с pandas, поскольку не компетентен. Но если, вы используете json в вашем API, то его можно сразу при преобразовании в питоновский словарь привести к нужному виду через параметра object_hooks, при вызове метода load (или loads, не имеет значения).
import json
# функция обработки
def parse_keys_to_int(initial_value):
if isinstance(initial_value, dict):
return {int(key):value for key,value in initial_value.items()}
return initial_value
# входные данные
d = {'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6]}}
# симуляция в json формат
f = json.dumps(d)
# обработка json, которые приходит с не верным типом данных ключей
c = json.loads(f, object_hook=parse_keys_to_int)
Результат
{3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6]}}
Преимущества:
Все равно, какая вложенность.
d = {'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6], '2': {'0': [6], '2': {'0': [6]}}}} # результат будет {3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6], 2: {0: [6], 2: {0: [6]}}}}Все равно, какая структура
json, это может быть список словарей (в терминологииpython)d = [{'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6], '2': {'0': [6], '2': {'0': [6]}}}}, {'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6], '2': {'0': [6], '2': {'0': [6]}}}}, {'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6], '2': {'0': [6], '2': {'0': [6]}}}}] # результат будет [{3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6], 2: {0: [6], 2: {0: [6]}}}}, {3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6], 2: {0: [6], 2: {0: [6]}}}}, {3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6], 2: {0: [6], 2: {0: [6]}}}}]Возможность добавить обаботку исключений и поведение для ключей другого типа, просто изменив функцию обработки
parse_keys_to_int()
Вариант через рекурсию и словарное включение:
def int_key(d):
return {int(k):int_key(v) for k, v in d.items()} if isinstance(d, dict) else d
dict_ = {'3': {'0': [68, 13]}, '4': {'0': [8, 58]}, '2': {'0': [6]}}
new_dict = int_key(dict_)
print(new_dict)
# {3: {0: [68, 13]}, 4: {0: [8, 58]}, 2: {0: [6]}}
P.S. Вариант кода для более сложного словаря:
def int_key(d):
return {int(k) if str.isdigit(k) else k:int_key(v) for k, v in d.items()} if isinstance(d, dict) else d
dict_ = {'5':
{'1': {'text_key_1': [309], 'text_key_2': 0},
'0': {'text_key_1': [406], 'text_key_2': 0}},
'6':
{'1': {'text_key_1': [311], 'text_key_2': 0},
'0': {'text_key_1': [446], 'text_key_2': 0}}
}
new_dict = int_key(dict_)
print(new_dict)
Вывод:
{5: {0: {'text_key_1': [406], 'text_key_2': 0},
1: {'text_key_1': [309], 'text_key_2': 0}},
6: {0: {'text_key_1': [446], 'text_key_2': 0},
1: {'text_key_1': [311], 'text_key_2': 0}}}
Возможно, в случае, если проверок нужно много, удобнее и правда делать через try/except.
Хоть и ответ мне помог, но потом ни один ответ не смог правильно работать при другом варианте словаря:
{'5':
{'1': {'text_key_1': [309], 'text_key_2': 0},
'0': {'text_key_1': [406], 'text_key_2': 0}},
'6':
{'1': {'text_key_1': [311], 'text_key_2': 0},
'0': {'text_key_1': [446], 'text_key_2': 0}}
}
Поэтому, пришлось вернутся к своему варианту, который маленько модернизировал, но зато он работает исправно. Оставлю, если кому понадобится:
def get_int_key(dict_in):
cash_ = {}
for key, val in dict_in.items():
try:
key = int(key)
except:
key = key
cash_[key] = get_int_key(val) if isinstance(val, dict) else val
return cash_