Vergleich mit doppelter Schleife möglich?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
animatrix
User
Beiträge: 6
Registriert: Montag 22. November 2010, 15:54

Hiho,

ich versuche gerade ein in Python geschriebenes Projekt mit etwas zu verfeinern,
ich habe insgesamt 3 Datensätze:
eine csv-datei mit Vorwahlen und dazugehörigen Postleitzahlen,
eine Datenbank mit Postleitzahlen und den dazugehörigen Aussendienstlern.

Nun möchte ich die Datensätze der CSV-Datei durchlaufen und vorwahl, plz und Aussendienstler ausgeben (reihe für reihe).
Postleitzahlen, die keinem Aussendienstler zugeordnet sind (bzw in der DB nicht vorhanden sind) sollen dabei mit "(n/v)" angegeben werden.

Mein bisheriger Ansatz:

Code: Alles auswählen

for vorwahl,plz in self.vorwahl2plz.items():
	for row in cursor: 
		if plz == row.a: 
			break
	if row.b != None:
		zeilen.append("'%s': '%s': '%s'" % (vorwahl, plz, row.b) )
	else:
		zeilen.append("'%s': '%s': '%s'" % (vorwahl, plz, "(n/v)") )
Das Problem dabei ist, dass die 2. Schleife nur beim ersten mal durchlaufen wird.

Ich hab zwar für solche Situationen folgenden Code gefunden:

Code: Alles auswählen

results = [(i, j, i * j) for i in range(1, number + 1)  
                             for j in range(1, number + 1)] 
    for number1, number2, result in results: 
        print(number1, "*", number2, "=", result) 
aber ich weiss beim besten Willen nicht, wie ich den so umstricken kann, dass er in meinen Code passt.

Ich würde mich freuen, wenn jemand von euch dafür eine lösung weiss :)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Eine einfache Lösung könnte so aussehen:

Code: Alles auswählen

plz2ad = dict((x.a, x.b) for x in cursor)
for vorwahl, plz in self.vorwahl2plz.items():
    zeilen.append("'%s': '%s': '%s'" % (vorwahl, plz, plz2ad.get(plz, "(n/v)")))
Falls du nicht das ganze Mapping im Speicher halten willst, dann solltest du besser eine Datenbankabfrage pro "zeilen.append" machen.

Sebastian
Das Leben ist wie ein Tennisball.
animatrix
User
Beiträge: 6
Registriert: Montag 22. November 2010, 15:54

Danke :)

Uff... Mit so wenig code hätte ich jetzt nicht gerechnet.
Ich muss zugeben, bisher hab ich noch nicht viel in Python gemacht,
deswegen kenn ich mich auch noch nicht ganz sogut damit aus (was sich hoffentlich in nächster Zeit ändert :) ).

Sehe ich das richtig, dass x.a und x.b in vorwahl & plz konvertiert werden, womit dann der wert aus der DB ermittelt wird?
Und wie wird bei dem Code der Aussendienstler in n/v umgewandelt, falls einer vorhanden ist? Geht das ohne Abfrage?

Zu der Datenbankabfrage bei jedem "zeilen.append"..
Dadurch würde die Abfrage aber mit sicherheit auch deutlich langsamer, oder?
Das ganze soll nämlich unsere Telefonsoftware etwas verbessern, indem die Mitarbeiter direkt sehen können, zu welchem Aussendienstler der Kunde gehört, der gerade anruft.
Da ich nur an die Software andocken kann, müsste dieses script mit sehr vielen einträgen öfters mal laufen, sollte also eher auf ein schnelles durchlaufen getrimmt sein.

Morgen werde ich wohl nicht dazu kommen, aber ich werde es Mittwoch auf jeden fall so probieren.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mein "plz2ad" hat den gleichen Zweck wie dein "vorwahl2plz". Nur ist "plz2ad" eine Abbildung von Postleitzahl auf Außendienstler und nicht von Vorwahl auf Postleitzahl. Lass dir den Wert einfach mal mit "print" ausgeben. Das Setzen von "n/v" erledigt hier die get-Methode auf Dictionaries. Das zweite Argument gibt an, was dass Ergebnis sein soll, wenn der Schlüssel (erstes Argument) nicht im Dictionary vorhanden ist.

Zur Geschwindigkeit: Darüber machst du dir erst Gedanken, wenn du wirklich Probleme hast oder dir sicher bist, dass sie auftreten werden. Nimm einfach die Lösung, welche du für am besten/leserlichsten/einfachsten/am schnellsten zu implementieren/wenigst fehleranfälligsten (was immer dir davon am wichtigsten ist) hältst und benutze sie. Meistens reicht das vollkommen aus.
Das Leben ist wie ein Tennisball.
animatrix
User
Beiträge: 6
Registriert: Montag 22. November 2010, 15:54

Hi,

ich habe es gerade so ausprobiert, wie du mir geschrieben hattest,
leider mag er das aber ebenfalls wohl nicht so gern.
Fehler beim Ausführen:

Code: Alles auswählen

  File "C:\Projekte\projekt.py", line 133, in
 <module>
    js_string = processor.get_javascript_dictionary_string()
  File "C:\Projekte\projekt.py", line 112, in
 get_javascript_dictionary_string
    zeilen.append("'%s': '%s': '%s'" % (vorwahl, plz, plz2ad.get(plz, "(n/v)"))) #<< zeile 112

TypeError: unhashable type: 'dict'
Ich hab zwar ein paar sachen dazu gefunden, aber alles Probleme mit für mich ziemlich komplexen codes.
Bedeutet das nun, dass ich in zeilen.append kein dictionary hinzufügen kann, oder das irgendwas falsch deklariert ist?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Die Meldung sagt dir, dass du Dictionaries nicht als Schlüssel verwenden kannst. Wahrscheinlich steckt in "plz" nicht das drin was du erwartest. Lass dir vor der Zeile mit dem append mal die entsprechenden Werte ausgeben.
Das Leben ist wie ein Tennisball.
animatrix
User
Beiträge: 6
Registriert: Montag 22. November 2010, 15:54

Mein fehler, ich hatte plz hier abgekürzt und im Code war es daten['plz'].

Das Ergebnis ist nun soweit fast ok.
Vorwahl gibt eine Liste aller vorwahlen aus,
plz gibt eine Liste aller Postleitzahlen aus
und plz2ad.get(daten['plz'], "(n/v)") gibt eine Liste aller Sachbearbeiter aus, noch mit einem eingeschlichenen Fehler.

Nun habe ich noch 2 Probleme:
1) plz2ad.get(daten['plz'], "(n/v)") gibt aus:
- Sachbearbeiter
- (n/v) wenn kein Eintrag in der DB ist
- None wenn in der DB der Eintrag {null} ist.
Gibt es eine Möglichkeit das Dictionary um eine Abfrage zu erweitern, damit der {null}-Eintrag (der als None eingetragen wird) ebenfalls in (n/v) umzuwandeln?

2) Aus zeilen wird nun scheinbar eine endlosschleife.
Das müsst ich nochmal überprüfen, aber bei 3 Ausgabewerten und alles hintereinander weg dürfte er eigentlich bei weitem nicht über ne Minute Werte ausgeben.


EDIT: Das mit dem umwandeln war ne blöde frage,
ich brauchs ja eigentlich garnicht ins dictionary schreiben, sondern nur in dem Fall den zeilen.append ändern.
Hat sich damit geklärt, hab einfach ne Abfrage eingebaut am anfang der Schleife.

Problem macht weiterhin der Endlosvorgang, die csv hat zwar knapp 20.000 Zeilen, aber bei der Geschwindigkeit sollte es in 2min spätestens fertig sein, denke ich. Ich hab da das Gefühl, dass er sich da mehrfach wiederholt. Gibt es irgendeine Möglichkeit sowas zu kontrollieren?
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Zu Deinem None Problem:

Code: Alles auswählen

plz2ad = dict((x.a, x.b or '(n/v)') for x in cursor) # hier 
for vorwahl, plz in self.vorwahl2plz.items():
    zeilen.append("'%s': '%s': '%s'" % (vorwahl, plz, plz2ad.get(plz, "(n/v)") or '(n/v)')) # oder hier
Der Ausdruck a or b gibt b zurück, wenn bool(a) False ist.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

animatrix hat geschrieben:Problem macht weiterhin der Endlosvorgang, die csv hat zwar knapp 20.000 Zeilen, aber bei der Geschwindigkeit sollte es in 2min spätestens fertig sein, denke ich. Ich hab da das Gefühl, dass er sich da mehrfach wiederholt. Gibt es irgendeine Möglichkeit sowas zu kontrollieren?
Wie wär's mit einem geschickten "print"?
animatrix
User
Beiträge: 6
Registriert: Montag 22. November 2010, 15:54

Ich danke euch für eure Tipps und Anregungen :)
Das ganze habe ich nun so realisiert und hinbekommen, dass es funktioniert:

Code: Alles auswählen

plz2ad = {}
        for x in cursor:
            plz2ad[x[0]] = x[1]

        for vorwahl, daten in self.vorwahl2plz.items():
            # sb soll bei fehlendem PLZ-Eintrag oder bei Aussendienstler == NULL '(n/v)' sein 
            ad = plz2ad.get(daten['plz'], '(n/v)')
            if not ad:
                ad = '(n/v)'
            zeilen.append("'%s': '%s'" % (vorwahl, ad))
BlackJack

@animatrix: Die ersten drei sollten Zeilen kürzer gehen:

Code: Alles auswählen

plz2ad = dict(cursor)
animatrix
User
Beiträge: 6
Registriert: Montag 22. November 2010, 15:54

Danke dir, funktioniert genausogut und ist kürzer.
Ich glaub was optimierung in Python angeht werd ich wohl noch etwas lernen müssen,
ich hätt das jetzt sonst so gelassen *g*
Antworten