Zählen von Einträgen in einer Liste von dictionaries: for-Schleife vs. list comprehension mit Karte(itemgetter)
In ein Python-Programm, das ich Schreibe, habe ich im Vergleich mit einem for
Schleife und einer Schrittweite von Variablen versus Liste Verständnis mit map(itemgetter)
und len()
beim zählen der Einträge in Wörterbüchern, die in einer Liste. Es nimmt die gleiche Zeit, die mit einer einzelnen Methode. Mache ich etwas falsch oder gibt es einen besseren Ansatz?
Hier ist eine stark vereinfachte und verkürzte Datenstruktur:
list = [
{'key1': True, 'dontcare': False, 'ignoreme': False, 'key2': True, 'filenotfound': 'biscuits and gravy'},
{'key1': False, 'dontcare': False, 'ignoreme': False, 'key2': True, 'filenotfound': 'peaches and cream'},
{'key1': True, 'dontcare': False, 'ignoreme': False, 'key2': False, 'filenotfound': 'Abbott and Costello'},
{'key1': False, 'dontcare': False, 'ignoreme': True, 'key2': False, 'filenotfound': 'over and under'},
{'key1': True, 'dontcare': True, 'ignoreme': False, 'key2': True, 'filenotfound': 'Scotch and... well... neat, thanks'}
]
Hier ist die for
loop-version:
#!/usr/bin/env python
# Python 2.6
# count the entries where key1 is True
# keep a separate count for the subset that also have key2 True
key1 = key2 = 0
for dictionary in list:
if dictionary["key1"]:
key1 += 1
if dictionary["key2"]:
key2 += 1
print "Counts: key1: " + str(key1) + ", subset key2: " + str(key2)
Ausgang für die Daten oben:
Counts: key1: 3, subset key2: 2
Hier ist die andere, vielleicht mehr Pythonic, version:
#!/usr/bin/env python
# Python 2.6
# count the entries where key1 is True
# keep a separate count for the subset that also have key2 True
from operator import itemgetter
KEY1 = 0
KEY2 = 1
getentries = itemgetter("key1", "key2")
entries = map(getentries, list)
key1 = len([x for x in entries if x[KEY1]])
key2 = len([x for x in entries if x[KEY1] and x[KEY2]])
print "Counts: key1: " + str(key1) + ", subset key2: " + str(key2)
Ausgang für die Daten oben (dieselbe wie vorher):
Counts: key1: 3, subset key2: 2
Ich bin ein klein wenig überrascht, diese nehmen die gleiche Menge an Zeit. Ich Frage mich, ob es etwas schneller. Ich bin sicher, ich bin etwas Blick einfach.
Einer alternative, die ich betrachtet habe, ist das laden der Daten in eine Datenbank und dabei SQL-Abfragen, aber die Daten nicht beibehalten werden muss und ich würde ein Profil der overhead der Datenübertragung, etc., und kann eine Datenbank nicht immer verfügbar sein.
Ich habe keine Kontrolle über die ursprüngliche form der Daten.
Der code oben ist nicht für style-Punkte.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube, du bist die Messung falsch überschwemmen den code gemessen werden, in eine Menge Aufwand (der läuft bei top-Modul-Ebene anstatt in einer Funktion zu tun-Ausgang). Indem Sie die beiden Codefragmente in Funktionen namens
forloop
undwithmap
, und das hinzufügen einer* 100
auf der Liste-definition (nach der Schließung]
), um die Messung ein wenig substanziellen, ich sehe, auf meinen langsamen laptop:d.h., die angeblich "mehr pythonic" - Ansatz mit
map
ist drei mal langsamer als die Ebenefor
Ansatz-die Ihnen sagt, dass es nicht wirklich "mehr pythonic";-).Daneben der gute Python ist Einfachheit, die mir empfiehlt was ich Hybris-ly benannt...:
werden, die auf Messung, spart zwischen 10% und 20% der Zeit über die
forloop
Ansatz.* 100
auf die Daten, wie ich bereits in meinem Ein, um zu bekommen eine ziemlich große Anzahl von Daten für die Messung, also die "Verkürzung" war hoffentlich widersprochen (ich kann nicht sagen, über die "Vereinfachung" -- egal, ob es würde oder würde nicht auf die relative Leistung hängt davon ab, was genau wurde vereinfacht;-).for i in range(10000000): a = i
dauert 50% länger auf top-Ebene als eine Funktion. Danke! Normalerweise würde ich Funktionen verwenden, sowieso, aber ich habe einfach geschrieben was ich dachte, war straight-forward-test-code in meiner Frage (und die hand winkte es als "nicht für style-Punkte"). Wie Sie sagen, "Sie lernen jeden Tag etwas neues".