Единый лайнер для преобразования словарных значений в отдельный словарь - PullRequest
4 голосов
/ 27 марта 2020

У меня есть словарь dict1, значения которого также являются словарями

dict1 = 
  {
   0: {'test1': ['pass', 'pass']},
   1: {'test2': ['fail', 'pass']},
   2: {'test3': ['fail', 'fail']},
   3: {'test4': []},
   4: {'test5': ['pass']},
   5: {'test6': ['pass', 'pass']}
  }

Я хочу получить его значения как отдельный словарь dict2, я пробовал вот так

dict2 = {k:v for k,v in dict(dict1.values()).items()}

Я получая ошибку ниже

ValueError: dictionary update sequence element #0 has length 1; 2 is required

Ожидаемый результат

dict2 =
      {
      'test1': ['pass', 'pass'],
      'test2': ['fail', 'pass'],
      'test3': ['fail', 'fail'],
      'test4': [],
      'test5': ['pass'],
      'test6': ['pass', 'pass']
      }

Любая помощь приветствуется

Ответы [ 4 ]

3 голосов
/ 27 марта 2020

Вы можете * разделить значения dict на карту цепочки :

>>> from collections import ChainMap
>>> dict(ChainMap(*dict1.values()))
{'test6': ['pass', 'pass'],
 'test5': ['pass'],
 'test4': [],
 'test3': ['fail', 'fail'],
 'test2': ['fail', 'pass'],
 'test1': ['pass', 'pass']}

На самом деле карта цепочки также является типом отображения (аналог API для dict), так что вы можете не нужен внешний вызов dict вообще. Если вы хотите сохранить порядок, введите значения с помощью reversed.

1 голос
/ 27 марта 2020

Вы можете вкладывать циклы в словесное понимание.

dict2 = {k: v for d in dict1.values() for k, v in d.items()}

Вышеуказанный однострочный примерно эквивалентен

dict2 = {}
for d in dict1.values():
    for k, v in d.items():
        dict2[k] = v
1 голос
/ 27 марта 2020

Вы получаете ошибку из-за dict(dict1.values()). Вы преобразуете dict() в dict_values([{'test1': ['pass', 'pass']}, {'test2': ['fail', 'pass']},...]), который не является допустимым типом для преобразования в словарь, поскольку внутренние словари имеют длину 1 вместо 2, как предполагает ошибка. Вы можете проверить это с помощью [len(x) for x in dict1.values()], который вернет [1, 1, 1, 1, 1, 1].

Чтобы получить желаемый результат, вы можете использовать это словарное понимание :

>>> {key: value for inner_dict in dict1.values() for key, value in inner_dict.items()}
{'test1': ['pass', 'pass'], 'test2': ['fail', 'pass'], 'test3': ['fail', 'fail'], 'test4': [], 'test5': ['pass'], 'test6': ['pass', 'pass']}

, которое сначала будет проходить по values() из dict1 (так как нам не нужен внешний ключ). Затем он будет повторять items() внутреннего dict inner_dict и назначать пары значений ключа key: value.

Выше приведено то же, что и следующий вложенный l oop подход:

result = {}
for inner_dict in dict1.values():
    for key, value in inner_dict.items():
        result[key] = value

print(result)
# {'test1': ['pass', 'pass'], 'test2': ['fail', 'pass'], 'test3': ['fail', 'fail'], 'test4': [], 'test5': ['pass'], 'test6': ['pass', 'pass']}

Что может быть проще для чтения, если вы не знакомы с пониманием словарей ,

1 голос
/ 27 марта 2020

Вы можете использовать dict:

dict2 = dict(b for i in dict1.values() for b in i.items())

Выход:

{'test1': ['pass', 'pass'], 
 'test2': ['fail', 'pass'], 
 'test3': ['fail', 'fail'], 
 'test4': [], 
 'test5': ['pass'], 
 'test6': ['pass', 'pass']
}
...