2016-06-12 4 views
4

Ich habe ein Wörterbuch dct, für das ich möchte, dass jeder seiner Werte summiert wird, vorausgesetzt, ihre entsprechenden Schlüssel existieren in einer angegebenen Liste lst.Filterwerte in Python-Generatorausdrücken

Der Code, den ich bisher benutze ist:

sum(dct[k] for k in lst) 

In dem obigen Generator Ausdruck würde ich die KeyError im Falle einen Schlüssel aus der Liste behandeln möchte nicht in der Wörterbuch gefunden. Ich kann nicht finden, wie man (syntax-weise) entweder einen try - except Ansatz oder einen if - else Ansatz innerhalb dieses Generatorausdrucks implementiert.

Wenn ein Schlüssel aus der Liste nicht im Wörterbuch gefunden wird, sollte er die anderen Werte erhalten. Das Endergebnis der Summen sollte nicht durch fehlende Schlüssel beeinflusst werden. Falls keiner der Schlüssel existiert, sollte Null das Ergebnis der Summe sein.

+1

Sie können "try" nicht in einem Generatorausdruck verwenden. Warum nicht 'dct.get (k)' verwenden, was anstelle eines Fehlers 'None' ergibt, wenn der Schlüssel nicht gefunden wird? Was ist das richtige Verhalten für Ihren Code in dem Fall, in dem ein Schlüssel nicht gefunden wird (z. B. sollte er als "0" zählen)? – jonrsharpe

+0

Wenn ein Schlüssel nicht gefunden wird, sollte er mit den restlichen Schlüsseln fortfahren. (Ich werde meine Beschreibung aktualisieren, um diesen Fall zu erklären - danke, dass Sie dies notiert haben) – Yannis

Antwort

1

Nun, es gibt einige Möglichkeiten, bevorzugt man zu verwenden ist dict.get():

# 1 
sum(dct.get(k, 0) for k in lst) 
# 2 
sum(dct[k] for k in lst if k in dct) 

auch eine der Option ist lst vor iteraring darüber zu filtern:

sum(dct[k] for k in filter(lambda i: i in dct, lst)) 

Und Sie können als Alternative zu sumreduce function auf gefilterten Liste verwenden:

reduce(lambda a, k: a + dct[k], filter(lambda i: i in dct, lst)) 

Nun lasst uns schnellste Ansatz mit timeit finden:

from timeit import timeit 
import random 

lst = range(0, 10000) 
dct = {x:x for x in lst if random.choice([True, False])} 

via_sum = lambda:(sum(dct.get(k, 0) for k in lst)) 
print("Via sum and get: %s" % timeit(via_sum, number=10000)) 
# Via sum and get: 16.725695848464966 

via_sum_and_cond = lambda:(sum(dct[k] for k in lst if k in dct)) 
print("Via sum and condition: %s" % timeit(via_sum_and_cond, number=10000)) 
# Via sum and condition: 9.4715681076 

via_reduce = lambda:(reduce(lambda a, k: a + dct[k], filter(lambda i: i in dct, lst))) 
print("Via reduce: %s" % timeit(via_reduce, number=10000)) 
# Via reduce: 19.9522120953 

So ist die schnellste Möglichkeit ist, Einzelteile über if-Anweisung innerhalb zusammenzufassen Generator Ausdruck

sum(dct[k] for k in lst if k in dct) # Via sum and condition: 9.4715681076 

Gute Luc k!

+0

Große und vollständige Antwort. Neugierig, wenn Sie einen Einblick in den Vergleich dieser 4 Optionen bieten könnten; Insbesondere, wie die dritte Option mit den ersten beiden verglichen wird. Gibt es Effizienzgewinne oder einen eher "pythonischen" Ansatz? – Yannis

+0

@Yannis danke, sicher) siehe aktualisierte Antwort mit Zeitmetriken :) Meine Schätzung Gewinner Methode ist die meisten "Pythonic" zu) –

1
sum(dct[k] for k in lst if k in dct) 
+0

Hilfreiche Antwort in der Tat; Andere Leute haben diesen Ansatz auch erwähnt und von dem, was ich sehen kann, war dein nicht der schnellste. Sorry – Yannis

2

Sie können einfach .get() verwenden, um zu versuchen, den Wert für den Schlüssel aus dem Wörterbuch zu bekommen, und es sollte nicht zurückkehren None oder Ihre bereitgestellten Standard Parameter gefunden werden, die in diesem Fall 0 sein würden.

>>> dct = {1:2, 3:4, 5:6} 
>>> lst = [1,5] 
>>> sum(dct.get(k, 0) for k in lst) 
8  

Sollten einige (oder alle ) der Schlüssel nicht vorhanden ist, noch die Summe ordnungsgemäß funktioniert.

>>> lst = [10, 11] 
>>> sum(dct.get(k, 0) for k in lst) 
0 
5

Sie haben zwei Möglichkeiten:

Prüfen, ob der Schlüssel

sum(dct[k] for k in lst if k in dct) 

oder mit get

sum(dct.get(k, 0) for k in lst) 
existiert

wo dct.get(k, 0) kehrt dct[k] wenn k einen Schlüssel in dct ist oder 0 wenn nicht.

1

Sie die get -Methode der Wörterbücher verwenden können, einen Standardwert zur Verfügung zu stellen, wenn nicht gefunden:

sum(dct.get(k, 0) for k in lst) 
Verwandte Themen