Создайте новый вложенный словарь, используя вложенный ключ, значения

#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. Я думаю, что это, возможно, было потеряно при редактировании.