2017-01-13 3 views
0

Ich habe eine Liste der Wörterbücher in folgendem Format:Mehr pythonic Art und Weise zur Herstellung eines dict löschen, wenn ein Schlüssel etwas paßt

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

Ich mag das erste Wörterbuch entfernen, wo die name Wert entspricht. Gibt es einen besseren Weg, dies zu tun?

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

Ausgang:

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

Ihr Beispiel löscht nur die 'name' Schlüssel, nicht das gesamte Wörterbuch. – Jkdc

+1

Mögliches Duplikat von [Wie entferne ich einen Schlüssel aus einem Python-Wörterbuch?] (Http://stackoverflow.com/questions/11277432/how-to-remove-a-key-from-a-python-dictionary) – MYGz

+2

Es ist ein schlechte Praxis zu überschreiben Standard 'list' – Kh40tiK

Antwort

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

Erfüllt nicht die Anforderung, nur zuerst zu löschen, die übereinstimmt. – RemcoGerlich

+0

Dies wird nicht aus der ursprünglichen Liste entfernt. Und in Ihrem Beispiel können Sie 'filter' verwenden. –

+0

@RemcoGerlich. Vielen Dank. Meine Antwort wurde aktualisiert. – gipsy

1

Dies ist ein perfektes pandas Problem. pandas ist Teil der PyData Suite (glaube ich) und es ist weithin akzeptiert. Ich würde es für diese Art von Problem Fosho verwenden.

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

Ich würde sagen, 'Pandas' für solch eine einfache Aufgabe zu verwenden ist ein Overkill. –

+1

Hängt davon ab, wie groß das Wörterbuch ist. Wenn dies ein Spielzeugbeispiel für eine Textdatei ist, die 500 MB groß ist, wäre es besser, dies auf diese Weise zu tun. Ich versuche, 'For-Loops' zu vermeiden, wann immer ich kann, nachdem ich das Video von Jake Vanderplas angeschaut habe https://www.youtube.com/watch?v=EEUXKG97YRw –

+1

Nun, du hast einen Punkt hier. Wenn die Datenmenge groß ist, stimme ich zu, dass Sie vielleicht mit professionellen Tools arbeiten möchten (wo 'Pandas' genau richtig sind). Da die Frage nicht die Dimension des Problems aufzeigt, könnte eine einfachere Lösung geeigneter sein. Aber auf jeden Fall hat deine Antwort einen erzieherischen Wert, also ziehe ich meine frühere Aussage zurück. Mit 'Pandas' für diese Aufgabe lernt man ein nettes Werkzeug auf dem Weg, Overkill oder nicht! –

0

Aus Python-Dokumentation zu Wörterbüchern.

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

d.clear() werden alle Werte eines Wörterbuchs löschen.

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

Wenn das Wörterbuch in einer Liste von anderen, können Sie einfach Pop der Liste aus oder es wie folgt löschen.

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

Meiner Meinung nach filter Verwendung ist die pythonic Weg:

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

Dies gilt jedoch nicht aus der ursprünglichen Liste entfernen und ein neues erstellt im Speicher. Zuweisen von old_list = filter(...) Mimics Entfernen von der ursprünglichen (zumindest im lokalen Bereich) jedoch gibt es immer noch den Speicheraufwand. Für kleine Listen (und die meisten Fälle) spielt dies keine Rolle. Ist dies der Fall, dann könnte folgende besser geeignet sein:

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

"Das Zuweisen von' old_list = filter (...) '" hat NICHT den gleichen Effekt wie das Ändern der Liste, wenn es einen anderen Verweis auf die Liste gibt. Um nicht zu sagen, es ist eine gute Idee, eine Liste zu ändern, die geteilt wird, aber das ist eine andere Frage;) –

1

Wenn Sie ein Motto möchten, können Sie einen Generator Ausdruck mit next() verwenden könnten, die Kurzschlüsse, wenn Sie das erste Element gefunden haben, zu entfernen, und verwenden dann list.remove():

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

Beispiel:

>>> 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}] 

Hinweis: das wird ein erhöhen StopIteration ist die value nicht gefunden wird, die vermieden werden kann, aber es ist etwas länger, denn obwohl next() ein Standardargument hat, list.remove() nicht:

>>> 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

Ich bin verwirrt, warum Sie nicht getan haben: 'value_to_remove = next ((d für d in l if d [ 'name'] == value), None) ', und dann' l.remove (value_to_remove) wenn value_to_remove! = None' – lol

0

ich eine separate Nutzenfunktion schaffen würde, es zu tun. Der folgende erste bestimmt, welche Wörterbücher (falls vorhanden) die Kriterien erfüllen, und dann pop s (löscht) die erste gefundene Wörterliste.

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) 
Verwandte Themen