Удаление словаря в списке по значению
Есть список словарей:
list = [{'id': 123456, 'name': 'a'},
{'id': 456123, 'name': 'a'},
{'id': 789465, 'name': 'a'}]
Нужно из него удалить словарь со значением 'id' = 123456
Делал так:
for i, elem in enumerate(list):
if list[i]['id'] != 123456:
del list[i]
Но так не получается, так как после удаления i становится не актуальной и итерация не срабатывеает.
Подскажите, пожалуйста, как можно это сделать?
Ответы (3 шт):
Лучше не менять исходный список, а создавать новый:
lis1 = [{'id': 123456, 'name': 'a'},
{'id': 456123, 'name': 'a'},
{'id': 789465, 'name': 'a'}]
lst2 = []
for elem in lis1:
if elem['id'] == 123456:
lst2.append(elem)
# Или одной строкой:
# lst2 = [elem for elem in lst1 if elem['id'] == 123456]
Также добавлю, что не рекомендуется называть переменные именами совпадающими с именами встроенных функций и других объектов (list, set, dict и т.д.)
Проблема в том, что перебор вы делается по возрастающей, но при удалении новые индексы будут неактуальные, т.к. верхняя граница уменьшилась.
Решением будет удаление от конца к началу:
items = [
{'id': 123456, 'name': 'a'},
{'id': 456123, 'name': 'a'},
{'id': 789465, 'name': 'a'}
]
for i in reversed(range(len(items))):
if items[i]['id'] == 123456:
del items[i]
print(items)
# [{'id': 456123, 'name': 'a'}, {'id': 789465, 'name': 'a'}]
Тот же цикл, но без reversed:
for i in range(len(items) - 1, -1, -1):
if items[i]['id'] == 123456:
del items[i]
бывает условие слишком сложно для записи в одну стоку, тогда удобно использовать filter, если func вернет True - значение добавится, иначе нет
lis1 = [{'id': 123456, 'name': 'a'},
{'id': 456123, 'name': 'a'},
{'id': 789465, 'name': 'a'}]
def func(x):
if x['id'] == 123456:
return False
elif x['id'] % 19:
if x['name'] == 'a':
return True
elif x['name'] == 'b':
return False
return True
lis1 = list(filter(func, lis1))