简体   繁体   中英

Python dictionary comprehension with nested for

Having trouble turning these loops into a dictionary comprehension - it might be impossible.

The general idea is that I have a dictionary of excludes that looks like this:

excludes = {
    "thing1": ["name", "address"],
    "thing2": ["username"]
}

Then I have a larger dictionary that I want to "clean" using the exclusions

original_dict = {
    "thing1": {"name": "John", "address": "123 Anywhere Drive", "occupation": "teacher" },
    "thing2": {"username": "bearsfan123", "joined_date": "01/01/2015"},
    "thing3": {"pet_name": "Spot"}
}

If I run the following:

for k, v in original_dict.iteritems():
    if k in excludes.keys():
        for key in excludes[k]:
            del v[key]

I'm left with:

 original_dict = {
     "thing1": {"occupation": "teacher" },
     "thing2": {"joined_date": "01/01/2015"},
     "thing3": {"pet_name": "Spot"}
 }

This is perfect, but I'm not sure if I can better represent this as a dictionary comprehension - simply adding the keys I want rather than deleting the ones I don't.

I've gotten down to the second for but am not sure how to represent that in a

new_dict = {k: v for (k, v) in original_dict.iteritems()}
{k:{sub_k:val for sub_k, val in v.iteritems()
    if sub_k not in excludes.get(k, {})}  
 for k,v in original_dict.iteritems()}

Note the need for excludes.get(k, {}) .

After pasting in your data and running it in IPython:

In [154]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:{k:{sub_k:val for sub_k, val in v.iteritems()
:    if sub_k not in excludes.get(k, {})}  
: for k,v in original_dict.iteritems()}
:--
Out[154]: 
{'thing1': {'occupation': 'teacher'},
 'thing2': {'joined_date': '01/01/2015'},
 'thing3': {'pet_name': 'Spot'}}

I'd personally argue that the for-loop approach is more readable and just generally better and less surprising across the spectrum of different developer experience levels of potential code readers.

A slight variation of the for loop approach that doesn't require evil side-effects with del and uses an inner dict comprehension:

new_dict = {}
for k, v in original_dict.iteritems():
    k_excludes = excludes.get(k, {})
    new_dict[k] = {sub_k:sub_v for sub_k, sub_v in v.iteritems()
                   if sub_k not in k_excludes}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM