2010-09-02 7 views
102

Ich liebe es mit dem AusdruckFall unempfindlich ‚in‘ - Python

if 'MICHAEL89' in USERNAMES: 
    ... 

wo USERNAMES eine Liste ist


Gibt es eine Möglichkeit, Elemente mit Groß- und Kleinschreibung entsprechen oder muss ich verwenden eine benutzerdefinierte Methode? Ich frage mich nur, ob dafür extra Code geschrieben werden muss.

Danke an alle!

Antwort

122
if 'MICHAEL89' in (name.upper() for name in USERNAMES): 
    ... 

Alternativ:

if 'MICHAEL89' in map(str.upper, USERNAMES): 
    ... 

Oder ja, können Sie eine benutzerdefinierte Methode machen.

+6

'if‚CaseFudge'.lower() in [x.lower() für x in der Liste] '' – fredley

+32

[...] 'schafft die ganze Liste. '(name.upper() für name in USERNAMES)' würde nur einen Generator und einen String gleichzeitig erstellen - eine enorme Speicherersparnis, wenn Sie diese Operation häufig durchführen. (Noch mehr Einsparungen, wenn Sie einfach eine Liste von Benutzernamen in Kleinbuchstaben erstellen, die Sie jedes Mal für die Überprüfung wiederverwenden) – viraptor

+2

Ziehen Sie es vor, beim Erstellen des Diktats aus Leistungsgründen alle Schlüssel zu senken. – Ryan

6

Ich denke, Sie müssen etwas zusätzlichen Code schreiben. Zum Beispiel:

if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES): 
    ... 

In diesem Fall haben wir eine neue Liste mit allen Einträgen in USERNAMES bilden in Großbuchstaben umgewandelt und dann gegen diese neue Liste zu vergleichen.

aktualisieren

Wie @viraptor sagt, es ist noch besser, einen Generator statt map zu verwenden. Siehe @Nathonanswer.

+0

Oder Sie könnten 'itertools' Funktion' imap' verwenden. Es ist viel schneller als ein Generator, erreicht aber das gleiche Ziel. – wheaties

4

könnten Sie tun

matcher = re.compile('MICHAEL89', re.IGNORECASE) 
filter(matcher.match, USERNAMES) 

Updates: um ein wenig gespielt und denken Sie einen besseren Kurzschluss Art Ansatz bekommen konnten

matcher = re.compile('MICHAEL89', re.IGNORECASE) 
if any(ifilter(matcher.match, USERNAMES)): 
    #your code here 

Die ifilter Funktion von itertools mit, eine der meine Lieblingsmodule in Python. Es ist schneller als ein Generator, erstellt aber nur das nächste Element der Liste, wenn es aufgerufen wird.

+0

Nur hinzufügen, das Muster muss möglicherweise maskiert werden, da es Zeichen wie ".", "?" Enthalten könnte, die specail Bedeutung in regulären Ausdrucksmustern hat. Verwenden Sie re.escape (raw_string), um es zu tun –

15

Ich würde eine Wrapper machen, so dass Sie nicht-invasiv sein können. Minimal, zum Beispiel ...:

class CaseInsensitively(object): 
    def __init__(self, s): 
     self.__s = s.lower() 
    def __hash__(self): 
     return hash(self.__s) 
    def __eq__(self, other): 
     # ensure proper comparison between instances of this class 
     try: 
      other = other.__s 
     except (TypeError, AttributeError): 
      try: 
      other = other.lower() 
      except: 
      pass 
     return self.__s == other 

Nun if CaseInsensitively('MICHAEL89') in whatever: sollte je nach Bedarf verhalten (ob die rechte Seite ist eine Liste, dict oder gesetzt). (Es kann mehr Aufwand erfordern, um ähnliche Ergebnisse für die String-Inklusion zu erzielen, vermeiden Sie Warnungen in einigen Fällen, die unicode, usw. betreffen).

+3

das funktioniert nicht für dict versuchen, wenn CaseInsensitively ('MICHAEL89') in {'Michael89': True}: print "gefunden" –

+2

Xavier: Sie würden 'CaseInsensitively ('MICHAEL89 ') in {CaseInsensitively (' Michael89 '): True} 'damit das funktioniert, was wahrscheinlich nicht unter" Verhalten wie erforderlich "fällt. – Gabe

+0

So viel, weil es nur einen offensichtlichen Weg gibt, es zu tun. Das fühlt sich schwer an, es sei denn, es wird viel benutzt. Das heißt, es ist sehr glatt. – nmichaels

8

Normalerweise (zumindest in oop) formen Sie Ihr Objekt so, dass es sich so verhält, wie Sie es möchten. name in USERNAMES nicht Groß- und Kleinschreibung, so USERNAMES Bedürfnisse sich ändern:

class NameList(object): 
    def __init__(self, names): 
     self.names = names 

    def __contains__(self, name): # implements `in` 
     return name.lower() in (n.lower() for n in self.names) 

    def add(self, name): 
     self.names.append(name) 

# now this works 
usernames = NameList(USERNAMES) 
print someone in usernames 

Das Tolle an diesem ist, dass es den Weg für viele Verbesserungen öffnet, ohne Code außerhalb der Klasse zu ändern. Zum Beispiel könnten Sie die self.names in ein Set für schnellere Lookups ändern, oder berechnen Sie die (n.lower() for n in self.names) nur einmal und speichern Sie es auf der Klasse und so weiter ...

3

Hier ist eine Art und Weise:

if string1.lower() in string2.lower(): 
    ... 
+2

AttributeError: Objekt 'list' hat kein Attribut 'low' – Jeff

Verwandte Themen