Smoothing the values ​​of each key in python

I have a dictionary like this:

migration_dict = {'30005': ['key42750','key43119', 'key44103', ['key333'],
['key444'], ['keyxx']], '30003': ['key43220', 'key42244','key42230',
['keyzz'], ['kehh']]}

      

How can I flatten the values ​​of each key to have something like this:

migration_dict = {'30005': ['key42750','key43119', 'key44103', 'key333',
'key444', 'keyxx'], '30003': ['key43220', 'key42244','key42230',
'keyzz', 'kehh']}

      

+3


source to share


5 answers


You can write a recursive function to flatten lists of values ​​and use it in dictionary comprehension to create a new dictionary:

def flatten(lst):
   for x in lst:
      if isinstance(x, list):
         for y in flatten(x): # yield from flatten(...) in Python 3
            yield y           #
      else:
         yield x

migration_dict = {k: list(flatten(v)) for k, v in dct.items()}
print(migration_dict)
# {'30005': ['key42750', 'key43119', 'key44103', 'key333', 'key444', 'keyxx'], '30003': ['key43220', 'key42244', 'key42230', 'keyzz', 'kehh']}

      



It handles any nesting depth in lists of dict values.

+9


source


for key in migration_dict:
    for i in migration_dict[key]:
        if type(i) == list:
            migration_dict[key].remove(i)
            for element in i:
                migration_dict[key].append(element)

      



This loop should now do it. Note, however, that this only works if the inner list contains no more lists. If this happens, you might have to make a recursive function that flattens it out for you.

+2


source


If you don't mind using a third party extension, you can use 1 and dictation comprehension:iteration_utilities.deepflatten

>>> from iteration_utilities import deepflatten
>>> {key: list(deepflatten(value, ignore=str)) for key, value in migration_dict.items()}
{'30003': ['key43220', 'key42244', 'key42230', 'keyzz', 'kehh'],
 '30005': ['key42750', 'key43119', 'key44103', 'key333', 'key444', 'keyxx']}

      

This will align all duplicate items in your values ​​(except for strings).


1 Disclaimer: I am the author of this library

+2


source


Here he is:

Consider this dict, the same structure:

m =  {'a': ['k1', 'k2', 'k3', ['k4'], ['k5'], ['k6']],
     'b': ['k1', 'k2', 'k3', ['k4'], ['k5'], ['k6']]}

import itertools

d = {k:list(itertools.chain.from_iterable(itertools.repeat(x,1) if isinstance(x, str) else x for x in v)) for k,v in m.iteritems()}

{'a': ['k1', 'k2', 'k3', 'k4', 'k5', 'k6'],
 'b': ['k1', 'k2', 'k3', 'k4', 'k5', 'k6']}

      

You can also use a third party library more-iterools

,

t = {k: list(more_itertools.collapse(v, base_type=str)) for k,v in m.iteritems()}

 {'a': ['k1', 'k2', 'k3', 'k4', 'k5', 'k6'],
 'b': ['k1', 'k2', 'k3', 'k4', 'k5', 'k6']}

      

0


source


If it's important to have flat values ​​in your dictionary, perhaps you could create a function that will get rid of all (multidimensional) lists before adding them to the dictionary?

def flatten_values(value):
      if type(value) == list:
           for i in value:
                return i

      

Hope it helps, can't do it in comment because I don't have enough rep;)

0


source







All Articles