Удаление ключ-значение по фильтру
Необходимо удалить ключ значение из словаря:
Вот код:
leads = [{'id': 'value2', 'num': 523541, 'status_id': 321, 'group_id': 721},{'id': 'value1', 'num': 123456, 'status_id': 123, 'group_id': 127}]
def removekey(d, key):
r = dict.copy(d)
del r[key]
return r
for i, elem in enumerate(leads):
for key in leads[i]:
if key != 'id':
test = removekey(leads[i], key)
То есть по сути хочу удалить все ключ-значение кроме ключа 'id'. Ошибок нет, но весь словарь остается и не удаляется, хотя в removekey заходит. Подскажите, пожалуйста, почему не удаляет?
Ответы (4 шт):
Для удаления значений из словаря используйте метод dict.pop.
Пример:
leads = [{'id': 'value2', 'num': 523541, 'status_id': 321, 'group_id': 721},{'id': 'value1', 'num': 123456, 'status_id': 123, 'group_id': 127}]
for d in leads:
for key in list(d.keys()):
if key != 'id':
d.pop(key)
print(leads)
# [{'id': 'value2'}, {'id': 'value1'}]
Для нескольких ключей проверка была бы например такая:
if key not in ('id', 'num'):
Вы в функции removekey делаете копию словаря, из нее удаляете ключ. Естественно, исходный словарь не изменится. Можно просто менять исходный словарь без создания копии:
leads = [{'id': 'value2', 'num': 523541, 'status_id': 321, 'group_id': 721},{'id': 'value1', 'num': 123456, 'status_id': 123, 'group_id': 127}]
for i, elem in enumerate(leads):
# Набор ключей собирается в список,
# чтобы избежать исключения "RuntimeError: dictionary changed size during iteration"
for key in list(elem):
if key != 'id':
del elem[key]
print(leads)
Другой вариант решения - через генератор словаря (dict comprehension):
leads = [{'id': 'value2', 'num': 523541, 'status_id': 321, 'group_id': 721},{'id': 'value1', 'num': 123456, 'status_id': 123, 'group_id': 127}]
for i, elem in enumerate(leads):
leads[i] = {key: value for key, value in elem.items() if key == 'id'}
print(leads)
Вообще, если нужно значение только по одному ключу, то внутренний цикл не нужен, можно просто брать значение по этому ключу, и записывать в новый словарь:
leads = [{'id': 'value2', 'num': 523541, 'status_id': 321, 'group_id': 721},{'id': 'value1', 'num': 123456, 'status_id': 123, 'group_id': 127}]
for i, elem in enumerate(leads):
if 'id' in elem:
leads[i] = dict(id=elem['id'])
else:
leads[i] = dict() # Учитываем случай, когда данного ключа нет в словаре
print(leads)
Всем спасибо! Решение нашел:
leads = [{'id': 'value2', 'num': 523541, 'status_id': 321, 'group_id': 721},{'id': 'value1', 'num': 123456, 'status_id': 123, 'group_id': 127}]
test = copy.deepcopy(leads)
for i, elem in enumerate(leads):
for key in leads[i]:
if key != 'id':
test[i].pop(key)
Вариант решения в одну строчку :)
leads = [{'id': 'value2', 'num': 523541, 'status_id': 321, 'group_id': 721},{'id': 'value1', 'num': 123456, 'status_id': 123, 'group_id': 127}]
leads = [dict(filter(lambda x: x[0] == 'id', d.items())) for d in leads]
На выходе:
# [{'id': 'value2'}, {'id': 'value1'}]
Как вариант можно ещё вот так:
leads =[{k: v} for d in leads for k,v in d.items() if k == 'id']