2017-01-13 2 views
0

У меня есть список словарей, в следующем формате:Более вещий способ удаления Dict если ключ соответствует что-то

list = [ 
{'name':'bob','age':12}, 
{'name':'jill','age':34} 
] 

Я хочу удалить первый словарь, где name приравнивает значение. Есть ли лучший способ сделать это?

value = 'bob' 
for dict in list: 
    if dict['name'] == value: 
     list.remove(dict) 
     break 

Выход:

list = [ 
{'name':'jill','age':34} 
] 
+0

Ваш пример удаляет только 'ключ name', а не весь словарь. – Jkdc

+1

Возможный дубликат [Как удалить ключ из словаря python?] (Http://stackoverflow.com/questions/11277432/how-to-remove-a-key-from-a-python-dictionary) – MYGz

+2

Это неправильная практика для перезаписи по умолчанию 'list' – Kh40tiK

ответ

1
list1 = [ 
{'name':'bob','age':12}, 
{'name':'jill','age':34} 
] 

value = 'bob' 

for i, item in enumerate(list1): 
    if item['name'] == value: 
    list1.pop(i) 
    break 
+0

Не соответствует требованию только удалять первое совпадение. – RemcoGerlich

+0

Это не удаляется из первоначального списка. И в вашем примере вы можете использовать 'filter'. –

+0

@RemcoGerlich. Благодарю. Обновлен мой ответ. – gipsy

1

Это идеальный pandas проблема. pandas является частью набора PyData (я думаю), и это широко принято. Я бы использовал его для этого типа проблем fosho.

Python 3.5.2 |Anaconda custom (x86_64)| (default, Jul 2 2016, 17:52:12) 
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import pandas as pd 
>>> query_list = [ {'name':'bob','age':12}, {'name':'jill','age':34} ] 
>>> DF = pd.DataFrame(query_list) 
>>> DF 
    age name 
0 12 bob 
1 34 jill 
>>> mask = DF["name"] != "bob" 
>>> mask 
0 False 
1  True 
Name: name, dtype: bool 
>>> DF2 = DF.loc[mask,:] 
>>> DF2 
    age name 
1 34 jill 
>>> DF2.to_dict() 
{'age': {1: 34}, 'name': {1: 'jill'}} 
+7

Я бы сказал, что использование 'pandas' для такой простой задачи - перебор. –

+1

Зависит от того, насколько велик словарь. Если это игрушечный пример текстового файла размером 500 МБ, тогда было бы лучше сделать это таким образом. Я стараюсь избегать 'for-loops' всякий раз, когда я могу после просмотра видео Jake Vanderplas https://www.youtube.com/watch?v=EEUXKG97YRw –

+1

Ну, у вас есть точка здесь. Когда массивы данных велики, я согласен с тем, что вы можете работать с профессиональными инструментами (где 'pandas' входит в правильное положение). Поскольку вопрос не раскрывает размерности проблемы, более удобное решение может быть более уместным. Но в любом случае ваш ответ имеет образовательное значение, поэтому я возвращаюсь к предыдущему утверждению. Используя 'pandas' для этой задачи, вы узнаете о хорошем инструменте по пути, излишнем или нет! –

0

Из документации python по словарям.

https://docs.python.org/3/library/stdtypes.html#dict

d.clear() удаляет все значения словаря.

value = 'bob' 
for dict in list: 
    if dict['name'] == value: 
     #Empty dictionary of all values, will now return {} 
     dict.clear() 
     break 

Если словарь находится в списке других, вы можете просто вытолкнуть его из списка или удалить его, как это.

list2 = [x for x in list1 if x != {}] 
0

На мой взгляд, используя filter самый вещий способ:

new_list = filter(lambda x: x['name'] != value, original_list) 

Однако это не снимает из исходного списка и создает новый в памяти. Присвоение old_list = filter(...) имитирует удаление из исходного (по крайней мере, в локальной области), однако все еще накладные расходы на память. Для небольших списков (и в большинстве случаев) это не будет играть роли. Если это произойдет, то следующий может быть более подходящим:

for item in original_list: 
    if item['name'] == value: 
     original_list.remove(item) 
     break 
+0

"Присвоение' old_list = filter (...) '" не имеет такого же эффекта, как изменение списка на месте, если есть какая-либо другая ссылка на список. Не сказать, что это хорошая идея изменить на месте список, который является общим, но это другой вопрос;) –

1

Если вы хотите один лайнер, вы можете использовать выражение генератор с next(), какие короткие замыкания, как только вы обнаружили, что первый элемент, чтобы удалить, и затем использовать list.remove():

l.remove(next(d for d in l if d['name'] == value)) 

Пример:

>>> l = [{'name':'bob','age':12},{'name':'jill','age':34}] 
>>> value = 'bob' 
>>> l.remove(next(d for d in l if d['name'] == value)) 
>>> l 
[{'name': 'jill', 'age': 34}] 

Примечание это повысит StopIteration является value не найден, который можно избежать, но это немного больше, потому что, хотя next() имеет аргумент по умолчанию, list.remove() не:

>>> l = [{'name':'bob','age':12},{'name':'jill','age':34}] 
>>> value = 'bob' 
>>> value_to_remove = next((d for d in l if d['name'] == value), None) 
>>> 'Value not in list' if value_to_remove is None else l.remove(value_to_remove) 
>>> l 
[{'name': 'jill', 'age': 34}] 
>>> value_to_remove = next((d for d in l if d['name'] == value), None) 
>>> 'Value not in list' if value_to_remove is None else l.remove(value_to_remove) 
'Value not in list' 
+0

Я смущен, почему вы этого не сделали: 'value_to_remove = next ((d для d в l, если d [ 'name'] == value), None) ', а затем' l.remove (value_to_remove), если value_to_remove! = None' – lol

0

Я хотел бы создать отдельную функцию полезности, чтобы сделать это. Сначала определяется, какие (если есть) словари соответствуют критериям, а затем pop s (удаляет) первый найденный.

from operator import itemgetter 

people = [ 
    {'name': 'bob', 'age': 12}, 
    {'name': 'jill', 'age': 34}, 
    {'name': 'bob', 'age': 14}, 
] 

def remove(name, seq): 
    """Remove first dictionary in seq with 'name' entry equal to name.""" 
    matches = [i for i,n in enumerate(map(itemgetter('name'), seq)) if n == name] 
    if matches: 
     seq.pop(matches[0]) 


remove('bob', people) 
print(people) # -> [{'name': 'jill', 'age': 34}, {'name': 'bob', 'age': 14}] 
0
list1 = [ 
    {'name': 'bob', 'age':12}, 
    {'name': 'jill', 'age':34} 
] 

map(lambda d: d.pop('name', 0) if d['name'] == 'bob' else d, list1) 
Смежные вопросы