#python #dictionary
Вопрос:
У меня есть словарь пар ключ-значение, где значение само по себе является словарем. Я хотел бы изменить имена ключевых значений в этом вложенном словаре на основе предопределенного преобразования.
Я использую два списка для сопоставления значений вложенных ключей, которые я пытаюсь сопоставить ( Old_item1
должны стать New_item1
):
comparison_list = ['Old_item1', 'Old_item2'] new_prods = ['New_item1', 'New_item2'] old_dict = { 'Company1': { 'Old_item1': { 'key1': val, 'key2': val }, 'Old_item2': { 'key1': val, 'key2': val } } }
Я попробовал это:
new_dict = {} for i in comparison_list: for j in new_prods: new_dict['Company1'][j] = test['Company1'][i]
Я получаю ошибку ключа: KeyError: 'Company1'
Желаемый результат для каждого элемента, который я добавляю в каждый список, таков:
new_dict = { 'Company1': { 'New_item1': { 'key1': val # old item key, val 'key2': val # old item key, val } } }
Комментарии:
1. Вы, вероятно, захотите в качестве промежуточного шага настроить словарь, который сопоставляет старые ключи с новыми ключами (используйте
zip
два списка для итерации при построении этого).2. Правка Натаниэля Форда заставляет меня казаться намного умнее, чем я есть на самом деле
3. @chasedcribbet Чушь собачья! Вы достаточно умны — я надеюсь, что редактирование поможет научить широко используемому языку для такого рода вещей, но я также хочу быть уверенным, что вы не чувствуете необходимости извиняться за то, что задали вопрос или были новичком в этой конкретной области знаний. Вот почему мы все здесь!
4. @Натаниэл, Не волнуйся. Просто пытаюсь посмеяться
5. @OlavAga сделал хороший вывод ниже. Теперь вопрос выглядит так, как будто я хотел изменить имена, но то, что я хотел, — это новый, отдельный диктант.
Ответ №1:
Вы можете составить словарь сопоставлений старых элементов с новыми, а затем использовать его для создания нового под-словаря для каждой компании. Затем это нужно завернуть во внешний цикл по компаниям (хотя здесь есть только один).
Например:
comparison_list = ['Old_item1', 'Old_item2'] new_prods = ['New_item1', 'New_item2'] old_dict = {'Company1': {'Old_item1': {'key1': 2, 'key2': 3}, 'Old_item2': {'key1': 4, 'key2': 5}}} key_mappings = dict(zip(comparison_list, new_prods)) new_dict = {k: {key_mappings[k1]: v1 for k1, v1 in v.items()} for k, v in old_dict.items()} print(new_dict)
дает:
{'Company1': {'New_item1': {'key1': 2, 'key2': 3}, 'New_item2': {'key1': 4, 'key2': 5}}}
Вот словарь сопоставлений key_mappings
, который мы использовали:
{'Old_item1': 'New_item1', 'Old_item2': 'New_item2'}
Комментарии:
1. Имейте в виду, что это решение не будет обрабатывать какие-либо ключи в old_dict, которые также не включены в сопоставление ключей, и даст вам
KeyError
.2. @Натаниэл Форд Да, это верно. Я предполагал, что все ключи будут в этих списках.
3. @NathanielFord Если ключей нет, то, я думаю, есть разные варианты в зависимости от требований. Возможно, следует использовать оригинальный ключ — и в этом случае a
get
, как вы предлагаете (здесь:key_mappings.get(k1, k1)
вместоkey_mappings[k1]
), прекрасно справится с этой задачей. Или, может быть, его следует полностью опустить, и в этом случаеif k1 in key_mappings
можно было бы использовать понимание внутреннего диктатора.4. Я согласен! Это не указано в ОП, и существует разная динамика в зависимости от того, в какую сторону вы хотите пойти. — что вы довольно хорошо описали. 🙂
Ответ №2:
Самый простой способ сделать это-заново создать свой словарь с пониманием:
new_dict = {company: update_item(v) for company, v in old_dict.items()}
Затем проанализируйте update_item
его собственную функцию. Вы могли бы сделать это встроенно, но это затрудняет понимание.
conversion_lookup = { 'Old_item1': 'NewItem1', 'Old_item2': 'NewItem2', } def update_item(item: dict) -gt; dict: return { conversion_lookup.get(k, k): v for k, v in item.items() } new_dict = {company: update_item(v) for company, v in old_dict.items()}
Для преобразования здесь я использую словарь, описывающий преобразование. Если вам нужно построить это автоматически:
comparison_list = ['Old_item1', 'Old_item2'] new_prods = ['New_item1', 'New_item2'] conversion_lookup = { v: new_prods[idx] for idx, v in enumerate(comparison_list) }
Причина, по которой мне нравится словарь, заключается в том, что вы можете им пользоваться some_dict.get(a_value, a_default_value)
. Затем, если вашего значения нет в словаре конверсий, вы можете вернуться к исходному значению. Вот что я здесь делаю:
conversion_lookup.get(k, k)
Во-вторых k
, это значение исходного элемента, которое полезно использовать, если в вашем списке конверсий нет того, что вы хотите.
Комментарии:
1. С твоей
for company, v in old_dict
, ты имеешь в видуfor company, v in old_dict.items()
? Если вы пройдетесь по словарю, вы просто получите ключи.2. Ага! Я делаю. 🙂 Спасибо вам!
Ответ №3:
Один из подходов состоит в том, чтобы делать это шаг за шагом. Сначала создайте диктанты с новыми именами и старыми ключами, затем удалите старые ключи и, наконец, добавьте новые имена.
# Keep the values from the old keys values = [old_dict['Company1'][old_name] for old_name in comparison_list] # Remove old names, and add in the for new_key, value, old in zip(new_prods, values, comparison_list): old_dict['Company1'].pop(old) old_dict['Company1'][new_key] = value
Комментарии:
1. Я не уверен, что происходит с
pop
этим ? Они должны быть просто перезаписаны, когда вы выполняете обновление, верно?2. Я думаю, что вы могли бы ошибиться на один в отношении уровня вложенности. Запуск вашего кода ставит
new_item1
и т. Д. На тот же уровень ,Company1
что и — а это не то, что вы хотите. Я думаю, что по этой причине это неудобный подход.3. Чтобы исправить последнее замечание @NathanielFord (с учетом существующего ограничения одного жестко заданного ключа верхнего уровня), просто измените
old_dict.update
наold_dict['Company1'].update
4. Как правило, в Python я нахожу более эффективным или более эффективным создать новый диктант и просто заменить предыдущий — то, как работает базовая динамика, в основном одно и то же, и об этом проще рассуждать. Кроме того, алани права в отношении исправления проблемы с обновлением, хотя вам придется делать это для каждой компании, и вам придется включить все это в цикл или что-то подобное, чтобы это сработало.
5. Мой первоначальный вопрос указывал на new_dict. Я думаю, что это, возможно, было потеряно при редактировании.