I would like to filter a list of (different) dictionaries based on a single key, not the value this key holds.
This is an example:
diclist_example = [{'animal': 'dog', 'legs': 'four'},
{'tvshow': 'Game of Thrones','rating': 'good'},
{'food': 'banana','color': 'yellow'},
{'animal': 'sheep', 'legs': 'four'},
{'tvshow': 'Gossip Girl','rating': 'bad'},
{'food': 'pizza','color': 'red-ish'}]
The problem with this is when I try to work with the 'animal'
values for example, I get a KeyError because some dictonaries do not contain the 'animal'
value.
I would like to generate a new list of dictionaries, containing all the dictionaries based on a key, for example, a list with all the animals, a list with all the tvshows of a list with all the foods.
You can do it with a lambda
function that filter elements with a list comprehension. This function will return a list of all identical elements
diclist_example = [{'animal': 'dog', 'legs': 'four'},
{'tvshow': 'Game of Thrones', 'rating': 'good'},
{'food': 'banana','color': 'yellow'},
{'animal': 'sheep', 'legs': 'four'},
{'tvshow': 'Gossip Girl', 'rating': 'bad'},
{'food': 'pizza', 'color': 'red-ish'}]
getAllElementsWithSameKey = lambda key: [d for d in diclist_example if key in d]
getAllElementsWithSameKey('animal')
You can create a list of all your dictionaries with
allElements = [getAllElementsWithSameKey(k) for k in ('animal','tvshow','food')]
create a list of dictionaries automatically using defaultdict
.
from collections import defaultdict
diclist_example=[{'animal': 'dog', 'legs': 'four'},
{'tvshow': 'Game of Thrones','rating': 'good'},
{'food': 'banana','color': 'yellow'},
{'animal': 'sheep', 'legs': 'four'},
{'tvshow': 'Gossip Girl','rating': 'bad'},
{'food': 'pizza','color': 'red-ish'}]
diclist = defaultdict(list)
for l in diclist_example:
for k in ('animal','food','tvshow'):
if k in l:
diclist[k].append(l)
break
print(diclist)
result:
defaultdict(<class 'list'>, {'food': [{'color': 'yellow', 'food': 'banana'}, {'color': 'red-ish', 'food': 'pizza'}], 'tvshow': [{'rating': 'good', 'tvshow': 'Game of Thrones'}, {'rating': 'bad', 'tvshow': 'Gossip Girl'}], 'animal': [{'legs': 'four', 'animal': 'dog'}, {'legs': 'four', 'animal': 'sheep'}]})
You should always check if the value exists before doing anything with it, using an if statement.
if myValue!=None: # or similar, depending on situation
# do something
To apply it to your example:
def zipDict(dicts):
allKeys = set(k for d in dicts for k in d.keys())
return {k:[d[k] for d in dicts if (k in d)] for k in allKeys}
###########
Here is a more verbose version:
def zipDict(dicts):
allKeys = set()
for d in dicts:
for key in d:
allKeys.add(key)
toReturn = {}
for key in allKeys:
toReturn[key] = []
for d in dicts:
if key in d: # THE GUARDIAN IF STATEMENT THAT PROTECTS YOU
toReturn[key].append(d[key])
return toReturn
sidenote: For other users who may stumble upon this post, here is a more efficient method: You should iterate over the dicts, NOT the allKeys, or else your algorithm is O(#keys * #dicts), rather than O(N):
def zipDict(dicts):
R = {}
for d in dicts:
for k,v in d.items():
if not k in R: # A PROTECTIVE IF STATEMENT
R[k] = []
R[k].append(v)
return R
You could use defaultdict to make it slightly nicer code:
def zipDict(dicts):
R = defaultdict(list)
for d in dicts:
for k,v in d.items():
R[k].append(v)
return dict(R)
Ex [Hard coded]:
l = [dict_elt for dict_elt in diclist_example if 'animal' in dict_elt]
您也可以尝试以下方法:
filter(lambda x: x["animal"] if "animal" in x else None, diclist_example)
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.