2015-08-01 11 views
7

Ich entwickle ein Python-Programm, um Namen von Städten in einer Liste von Datensätzen zu erkennen. Der Code, den ich bisher entwickelt haben, ist die folgende:Wie kann ich feststellen, welches Element in einer Liste eine any() -Funktion ausgelöst hat?

aCities = ['MELBOURNE', 'SYDNEY', 'PERTH', 'DUBAI', 'LONDON'] 

cxTrx = db.cursor() 
cxTrx.execute('SELECT desc FROM AccountingRecords') 

for row in cxTrx.fetchall() : 
    if any(city in row[0] for city in aCities) : 
     #print the name of the city that fired the any() function 
    else : 
     # no city name found in the accounting record 

Der Code funktioniert gut zu erkennen, wenn eine Stadt in der Liste aCities in der Abrechnungssatz gefunden, aber als die jede() Funktion nur True zurückgibt, oder Falsch Ich habe zu kämpfen, um zu wissen, welche Stadt (Melbourne, Sydney, Perth, Dubai oder London) den Ausgang ausgelöst hat.

Ich habe versucht mit aCities.index und Warteschlange aber bisher keinen Erfolg.

Antwort

10

Ich glaube nicht, dass es mit any möglich ist. Sie können next mit Standardwert verwenden:

for row in cxTrx.fetchall() : 
    city = next((city for city in aCities if city in row[0]), None) 
    if city is not None: 
     #print the name of the city that fired the any() function 
    else : 
     # no city name found in the accounting record 
4

Sie werden nicht, weil any nur einen booleschen Wert zurückgibt. Aber Sie können next verwenden:

city = next((city for city in aCities if city in row[0]), None) 
if city: 
    ... 

Mit dieser Syntax finden Sie die ersten city finden, die eine Teil der Beschreibung in der Datenbank Zeile gespeichert ist. Wenn es keinen gibt, ist der zweite Parameter z.B. Keine, wird zurückgegeben.

+0

Vielen Dank @JuniorCompressor! –

3

Nein, es möglich mit any ist. Es ist ein bisschen wie ein Trick - es „liest lustig“ - aber es funktioniert:

if any(city in row[0] and not print(city) for city in aCities): 
    # city in row[0] found, and already printed :) 
    # do whatever else you might want to do 
else: 
    # no city name found in the accounting record 

oder prägnanter, wenn alles, was Sie wirklich tun möchte, ist Druck die Stadt:

if not any(city in row[0] and not print(city) for city in aCities): 
    # no city name found in the accounting record 

Es funktioniert aus drei Gründen:

  1. any stoppt beim ersten true (truthy) Artikel,
  2. and ist ein Kurzschluss, so wird not print(city) wird nur ausgewertet, wenn city in row[0] wahr ist, und
  3. print gibt None zurück, also not print(...) ist immer True.

PS: Wie @falsetru weist darauf hin, in Python 2.x print ist keine Funktion, so dass Sie müssen zuerst sagen:

from __future__ import print_function 

Wie gesagt, es funktioniert für 3 Gründe - Python 3 Gründe;) Oh, warten - das sind 4 Gründe ...

+0

Clever, aber 'print' in Python 2.x ist eine Anweisung, keine Funktion. Sie sollten besser über 'from __future__ import print_function' sprechen. +1 – falsetru

1

der Vollständigkeit halber ist hier eine Lösung mit einer Standard-for-Schleife:

for city in aCities: 
    if city in row[0]: 
     print 'Found city', city 
     break 
else: 
    print 'Did not find any city' 

Dies sollte das gleiche Kurzschlussverhalten wie any haben, da es bei Erfüllung der Bedingung aus der for-Schleife ausbricht. Der else Teil wird ausgeführt, wenn die for-Schleife bis zum Ende ohne Unterbrechung läuft, siehe this question.

Obwohl diese Lösung mehr Zeilen verwendet, verwendet es tatsächlich weniger Zeichen als die anderen Lösungen, da es keinen Aufruf next(..., None) ist, ist es nicht die zusätzliche city = Zuordnung hat und es gibt keine zweite if city is None (auf Kosten eines zusätzlichen break). Wenn die Dinge komplizierter werden, ist es manchmal klarer, die for-Schleife explizit auszugeben und dann einige Generator-Ausdrücke und next-Anweisungen zusammenzufassen.

+0

Danke @ Bas-Swinckels. Der Code sollte ca. 10 Millionen Datensätze verarbeiten und die Städte-Liste wird ca. 500 Elemente umfassen. Ich mag deine Herangehensweise in Bezug auf Klarheit, aber was denkst du über die Leistung? –

+1

@LuisU. das hängt wirklich von Ihrer Anwendung ab, die einzige Möglichkeit, das zu wissen, besteht darin, Ihren Code zu profilieren (zB mit dem Befehl "timeit" in IPython oder mit dem [timeit] (https://docs.python.org/2/library/timeit) .html) Modul Wenn Sie einfach nur etwas drucken, machen Sie einige schwere Berechnungen, der Rest ist vernachlässigbar, ich könnte mir auch vorstellen, dass das Sprechen mit Ihrer Datenbank viel mehr Zeit in Anspruch nimmt als eine einfache Schleife über 5 Städte. –

+0

Bitte [starten Sie nicht zu optimieren] (http://c2.com/cgi/wiki?PrematureOptimization), bevor Sie wissen, dass es ein Problem gibt, versuchen Sie, klar und wartbare Code zuerst zu schreiben. Aber wenn Sie optimieren möchten, Beginnen Sie mit der Optimierung des Algorithmus, zB können Sie 'für Stadt in Liste_von_Städten' ändern (wobei die Rechenzeit linear mit der Länge der Liste ist), für' Stadt in Menge_von_Städten' (die konstante Laufzeit hat) Nur wenn es still ist Wenn Sie dann langsamer werden, beginnen Sie, alle Zeilen zu profilieren, und beginnen Sie sich Gedanken über die Geschwindigkeit von Python-Schleifen und integrierten Funktionen zu machen ons wie 'any'. –

Verwandte Themen