Iterating over nested dictionaries (Pythonic)

3

I always get off the hook when it comes to thinking of nested loopbacks to iterate over some container (typical of C / C ++) because I know that python has very particular ways of iterating over containers. To iterate over dictionaries of dictionaries I can only think of the solution by nesting loops like in:

>>> dic = {'section1': {'key1': 'value1', 'key2':'value2'}, 'section2': {'key3': 'value3', 'key4': 'value4'}}
>>> for x in dic:
...     print(dic[x])
... 
{'key3': 'value3', 'key4': 'value4'}
{'key2': 'value2', 'key1': 'value1'}
>>> for x in dic:
...     for y in dic[x]:
...         print(dic[x][y])
... 
value3
value4
value2
value1

Is there any more "Pythonic" way of doing the same? Who knows, using a single for

    
asked by anonymous 05.09.2016 / 19:33

2 answers

3

There are several pythonices : P can do:

Way 1

dic = {'section1': {'key1': 'value1', 'key2':'value2'}, 'section2': {'key3': 'value3', 'key4': 'value4'}}
values = [item for sublist in [dic[i].values() for i in dic] for item in sublist]
for val in values:
    print(val)

Explanation :

To get all the values of each dictionary we can do:

values = [dic[i].values() for i in dic] # [['value2', 'value1'], ['value3', 'value4']]

To turn this list of lists into one list, we do:

values = [item for sublist in values for item in sublist] # ['value4', 'value3', 'value2', 'value1']

Most simple way:

dic = {'section1': {'key1': 'value1', 'key2':'value2'}, 'section2': {'key3': 'value3', 'key4': 'value4'}}
valuesLists = [dic[i].values() for i in dic]
values = [item for sublist in valuesLists for item in sublist] # transformar numa só lista
for val in values:
    print(val)

Way 2

(in this case perhaps this was the one I would choose)

dic = {'section1': {'key1': 'value1', 'key2':'value2'}, 'section2': {'key3': 'value3', 'key4': 'value4'}}
values = [dic[j][i] for j in dic for i in dic[j]]
print('\n'.join(values)) # imprimir um valor por linha, se for so para isto nao e necessario o ciclo for

Up here we do a nested list compreenshion

Way 3

dic = {'section1': {'key1': 'value1', 'key2':'value2'}, 'section2': {'key3': 'value3', 'key4': 'value4'}}
values = []
valuesLists = [values.extend(dic[i].items()) for i in dic]
for k, v in values:
    print(k, v) # aqui imprime, chave valor... Se quiser que imprima só o valor retire o k do print

At the top we have the keys too, just for the value:

dic = {'section1': {'key1': 'value1', 'key2':'value2'}, 'section2': {'key3': 'value3', 'key4': 'value4'}}
values = []
valuesLists = [values.extend(dic[i].values()) for i in dic]
for v in values:
    print(v)

If you are running for just to print, you can achieve the same result by doing instead of the for cycle:

print('\n'.join(values))
    
05.09.2016 / 19:43
4

Another alternative is itertools.chain.from_iterable :

from itertools import chain

dic = {'section1': {'key1': 'value1', 'key2': 'value2'},
       'section2': {'key3': 'value3', 'key4': 'value4'}
      }

valores = chain.from_iterable(map(lambda sec: sec.values(), dic.values()))

for valor in valores:
    print(valor)
    # value1
    # value2
    # value3
    # value4

See DEMO

If you prefer to display the values immediately:

print ( list(chain.from_iterable(map(lambda sec: sec.values(), dic.values()))) )
# ['value1', 'value2', 'value3', 'value4']

See DEMO

    
06.09.2016 / 02:51