Single liner for converting dictionary values into a separate dictionary

Viewed 115

I have a dictionary dict1 whose values are also dictionaries

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

I want to get its values as a separate dictionary dict2, I have tried like this

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

I am getting an error below

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

Expected Output

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

Any help is appreciated

4 Answers

You can *splat the dict values into a chain map:

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

Actually a chain map is also a type of mapping (similar API to a dict) so you may not need the outer dict call at all. If you care to preserve ordering, then splat the values in with reversed.

You can use dict:

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

Output:

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

You are getting the error because of dict(dict1.values()). You are casting dict() to dict_values([{'test1': ['pass', 'pass']}, {'test2': ['fail', 'pass']},...]), which is not a valid type to convert to a dictionary, since the inner dictionaries are of length 1 instead of 2, as the error suggests. You can verify this with [len(x) for x in dict1.values()], which will return [1, 1, 1, 1, 1, 1].

To get the result you desire, you can use this dictionary comprehension:

>>> {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']}

Which will first iterate over the values() of dict1(since we don't need the outermost key). Then it will iterate the items() of the inner dict inner_dict and assign the key value pairs key: value.

The above is the same as the following nested loop approach:

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']}

Which might be easier to read if you are not familiar with dict comprehensions.

You can nest loops in dict comprehensions.

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

The above one-liner roughly is equivalent to

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