2017-05-19 6 views
1

Um die Liste der Wörterbücher aus leeren Werten zu filtern, muss ~ 30% der Daten aus den Wörterbüchern entfernt werden.Element aus dem Wörterbuch nach Schlüssel entfernen, während iteriert wird

So habe ich mit diesem Code am Ende:

qr = query_result 
    for row in qr: 
     for key, value in row.items(): 
      if value ==' ' or value == None, value == '': 
       del row[key] 

Allerdings gibt es ein Fehler während der Ausführung zunächst löschen Versuch:

RuntimeError: dictionary changed size during iteration

Nach ein bisschen suchen auf Stackoverflow Ich habe gefunden solution, die beinhaltet alle gelöschten Werte in separate Liste für die nachfolgende Löschung zu kopieren. Diese

delete = [] 
for k,v in dict.items(): 
    if v%2 == 1: 
     delete.append(k) 
for i in delete: 
    del dict[i] 

, Ansatz, verwandelt sich in einen solchen Code für meinen Fall:

qr = query_result 
for row in qr: 
    delete = [] 
    for key, value in row.items(): 
     if value == ' ' or value == '' or value == None: 
      delete.append(key) 
    for i in delete: 
     del row[i] 

die auch leidet unter gewissen RuntimeError.

So löschen Schleife außerhalb dict foreach Schleife sein sollte:

qr = query_result 
for row in qr: 
    delete = [] 
    for key, value in row.items(): 
     if value == ' ' or value == '' or value == None: 
      delete.append(key) 
for i in delete: 
    del row[i] 

Aber da Code leider nur korrekt letzte Zeile modifiziert.

Wie verarbeite ich alle Zeilen und lösche dann Mülldaten?

Hier werden einige Daten für den Test:

c = [{'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''}, 
    {'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''}] 

My Ausgang:

{'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''} 
{'A': 'B', 'C': '3', 'P': '343'} 

gewünschte Ausgabe:

{'A': 'B', 'C': '3', 'P': '343'} 
{'A': 'B', 'C': '3', 'P': '343'} 

Antwort

0

A one-liner:

c = [{k: v for k, v in d.items() if v not in [' ', '', None]} for d in c] 

Schleife über die Elemente von c und dann für jedes einzelne nur die passenden Schlüssel/Wert-Paare. Dies gibt:

[{'A': 'B', 'P': '343', 'C': '3'}, {'A': 'B', 'P': '343', 'C': '3'}] 
2

ist hier eine Version Ihr erstes Beispiel zu modifizieren, müssen Sie zu „kopieren“ Ihre Liste mit ihr wiederholen und zugleich zu löschen. Nachdem Sie mit der kopierten Liste iteriert haben, können Sie sie bei Bedarf aus der ursprünglichen Liste löschen.

import copy 

qr = [{'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''}, 
    {'A': 'B', 'C': '3', 'EE': None, 'P': '343', 'AD': ' ', 'B': ''}] 

for i, row in enumerate(copy.deepcopy(qr)): 
    for key, value in row.items(): 
     if value in {' ', None, ''}: 
      del qr[i][key] 

print(qr) 

Andere als die, in der Regel möchten Sie eine neue Liste erstellen, als von der ursprünglichen Liste zu löschen. Eine einfache Liste Verständnis wird der Trick:

qr = [{k:v for k, v in row.items() if v not in {' ', None, ''}} for row in qr] 

print(qr) # same result 

Ausgang für beide:

[{'A': 'B', 'C': '3', 'P': '343'}, 
{'A': 'B', 'C': '3', 'P': '343'}] 
1

Ihr Ansatz (Schlüssel sammeln, während laufen, löschen danach) ist richtig.

Hier ist Ihr Problem:

qr = query_result 
for row in qr: 
    delete = [] # <--- here 

Sie erstellen eine neue delete Liste jedes Mal, wenn eine neue Zeile berühren. Wenn irgendwelche Daten von einer vorherigen Zeile übrig waren, ist es verloren.

Stattdessen sollten Sie es auf dem gleichen Niveau (der Vertiefung) erstellen, wie Sie sich anschließend verwenden:

delete = [] # Only once for all rows. 
qr = query_result 
for row in qr: 
    # ... 

for k in delete: 
    del data[k] 
Verwandte Themen