Python Dictionary comprehension to copy some pairs to a new dictionary

為{幸葍}努か 提交于 2020-01-06 14:57:15

问题


While playing around with input validation, specifically checking whether the supplied data have all the required attributes specified, and discarding attributes that I don't want, I did something like this:

>>> input = {'v1': 'val1', 'a2':'val2', 'a3':'val3'} 
>>> print input
{'v1': 'val1', 'a3': 'val3', 'a2': 'val2'}
>>> goodkeys = ['a2', 'a3']
>>> print goodkeys
['a2', 'a3']
>>> output = {}
>>> for a in goodkeys:    
...   output[a] = input[a]
... 
>>> 
>>> print output
{'a3': 'val3', 'a2': 'val2'}

Which of course works. But it occurred to me that it may be possible to do this in a more pythonic way. I tried:

>>> output = {}
>>> print output
{}
>>> output = { a:v for a in goodkeys for v in input[a] }
>>> print output
{'a3': '3', 'a2': '2'}
>>> 

Which for half a second I thought worked, then I realized that the values are wrong. Is there a pretty Python method? And what happened, where did Python get those values?


回答1:


You could use dictionary view objects:

goodkeys = {'a2', 'a3'}
output = {a: input[a] for a in input.viewkeys() & goodkeys}

where goodkeys is a set; dict.viewkeys() produces a set-like object that reflects the contents of the dictionary, and & goodkeys produces the intersection between those keys and the goodkeys set. That way you only ever produce keys that are both in the input dictionary and the set of good keys.

You created a nested loop like this:

for a in goodkeys:
    for v in input[a]:
        # v is a single character in the string value

Demo:

>>> input = {'v1': 'val1', 'a2':'val2', 'a3':'val3'} 
>>> goodkeys = {'a2', 'a3'}
>>> {a: input[a] for a in input.viewkeys() & goodkeys}
{'a3': 'val3', 'a2': 'val2'}

Since input[a] is a string, your inner loop produced the individual characters of each value:

>>> for a in goodkeys:
...     for v in input[a]:
...         print a, v
... 
a3 v
a3 a
a3 l
a3 3
a2 v
a2 a
a2 l
a2 2

Keys must be unique, so for a2, one of v, a, l and 2 is picked with the others discarded. The dictionary comprehension sets 'a2': 'v' first, then 'a2': 'a', etc. and only 'a2': '2' remains in the output, in the end.

You didn't need to use that inner loop; you could have stuck with:

{a: input[v] for a in goodkeys}

except that if there are any keys in goodkeys that are not in input you'd get a KeyError. The dictionary view approach neatly sidesteps that issue.




回答2:


output = { a:input[a] for a in goodkeys }

Your second for iterates through the characters of the string values.




回答3:


You may be over thinking this. Just try changing

output = { a:v for a in goodkeys for v in input[a] }

to simply...

output = { a:input[a] for a in goodkeys }


来源:https://stackoverflow.com/questions/27447684/python-dictionary-comprehension-to-copy-some-pairs-to-a-new-dictionary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!