Question

So I'm wondering if anyone can help me out with this issue I'm having.

Lets assume I have a dictionary:

d = {1: {2: 3}, 4: 5}

I want to create a dictionary of any contained dictionaries:

wanted_result = {2: 3}

what I am trying is this:

e = {inner_key: d[key][inner_key] for key in d.keys() for inner_key in d[key].keys() if isinstance(d[key], dict)}

However this is causing me to get an error saying that ints don't have keys, which I know, but I thought my conditional would exclude say 4 from my example from being included in the comprehension.

Was it helpful?

Solution

My first idea was something like this:

d = {1: {2: 3}, 4: 5, 6: {7: 8}}
generator = (x.items() for x in d.itervalues() if type(x) == dict)
s = dict(sum( generator, list() )) 
# s = {2: 3, 7: 8}

But, in order to avoid letting sum() construct a large temporary list of all the items() you may use itertools.chain and iteritems() instead:

# chain "concatenates" iterables
from itertools import chain
d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = dict(chain( *(x.iteritems() for x in d.itervalues() if type(x) == dict) ))
# s = {2: 3, 7: 8}

You should be aware of edge cases. Especially if identical keys are in the part-dictionaries these will necessarily collapse somehow.


If you also want to support subclasses of dict to be collected from your d.values(), you may indeed want to use isinstance instead of type. See this question for details.

OTHER TIPS

d = {1: {2: 3}, 4: 5, 6: {7: 8}}
s = {k: v for elem in d.values() if type(elem) is dict for k, v in elem.items()}
>> {2: 3, 7: 8}

In this case, I would recommend you a for-loop and the update method:

d = {1: {2: 3}, 4: 5, 6: {7: 8}}
inner_dicts = {}
for val in d.values():
    if type(val) is dict:
        inner_dicts.update(val)
print inner_dicts
# {2: 3, 7: 8}

The following list comprehension will return each value that is a dict:

>>> d = {1: {2: 3}, 4: 5}
>>> [d[i] for i in d.keys() if isinstance(d[i],dict)]
[{2: 3}]
d = {1: {2: 3}, 4: 5,'j':{7:8}}
e={y:d[x][y] for x in d if isinstance(d[x],dict) for y in d[x]}
print(e)

{2: 3, 7: 8}

Other way using lambda

(lambda x: {k:v for x in d.values() if type(x) == dict for k,v in x.items()})(d)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top