Фильтровать список словарей по ключу (а не по значению ключа) в Python
Я хотел бы отфильтровать список (разных) словарей по одному ключу, а не по значению этого ключа.
Это пример:
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'}]
Проблема с этим, когда я пытаюсь работать с 'animal'
значения, например, я получаю KeyError, потому что некоторые диктофоны не содержат 'animal'
значение.
Я хотел бы создать новый список словарей, содержащий все словари, основанные на ключе, например, список со всеми животными, список со всеми сериями из списка со всеми продуктами.
5 ответов
Вы можете сделать это с lambda
функция, которая фильтрует элементы с пониманием списка. Эта функция вернет список всех идентичных элементов
getAllElementsWithSameKey = lambda key:[d for d in diclist_example if key in d]
getAllElementsWithSameKey('animal')
Вы можете создать список всех своих словарей с
allElements = [getAllElementsWithSameKey(k) for k in ('animal','tvshow','food')]
Ex [Жесткий код]:
l = [dict_elt для dict_elt в diclist_example, если 'animal' в dict_elt]
Создать список словарей автоматически, используя 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)
результат:
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'}]})
Вы также можете попробовать следующий подход:
filter(lambda x: x["animal"] if "animal" in x else None, diclist_example)
Вы должны всегда проверять, существует ли значение, прежде чем что-либо делать с ним, используя оператор if.
if myValue!=None: # or similar, depending on situation
# do something
Чтобы применить его к вашему примеру:
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}
###########
Вот более подробная версия:
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: для других пользователей, которые могут наткнуться на этот пост, есть более эффективный метод: вам следует перебирать слова dict, а не allKeys, иначе ваш алгоритм будет O(#keys * #dicts), а не 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
Вы можете использовать defaultdict, чтобы сделать его немного лучше:
def zipDict(dicts):
R = defaultdict(list)
for d in dicts:
for k,v in d.items():
R[k].append(v)
return dict(R)