Ich liebe es, den Ausdruck zu benutzen
if 'MICHAEL89' in USERNAMES:
...
dabei ist USERNAMES
eine Liste
Gibt es eine Möglichkeit, Elemente mit Groß-/Kleinschreibung zuzuordnen, oder muss ich eine benutzerdefinierte Methode verwenden? Ich frage mich nur, ob es notwendig ist, zusätzlichen Code dafür zu schreiben.
Danke an alle!
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
...
Alternative:
if 'MICHAEL89' in map(str.upper, USERNAMES):
...
Oder ja, Sie können eine benutzerdefinierte Methode erstellen.
Ich würde ein Wrapper machen, damit Sie nicht invasiv sein können. 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 sollte sich if CaseInsensitively('MICHAEL89') in whatever:
wie gewünscht verhalten (ob die rechte Seite eine Liste, ein Diktat oder eine Menge ist). (Möglicherweise ist mehr Aufwand erforderlich, um ähnliche Ergebnisse für das Einschließen von Zeichenfolgen zu erzielen. Vermeiden Sie in einigen Fällen Warnungen, die unicode
usw. betreffen.).
Normalerweise (zumindest in oop) gestalten Sie Ihr Objekt so, dass es sich so verhält, wie Sie es möchten. name in USERNAMES
unterscheidet nicht zwischen Groß- und Kleinschreibung, daher muss USERNAMES
geändert werden:
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 daran ist, dass es den Weg für viele Verbesserungen ebnet, ohne dass Code außerhalb der Klasse geändert werden muss. Zum Beispiel könnten Sie das self.names
zu einem Satz für schnellere Suchvorgänge oder zum Berechnen des (n.lower() for n in self.names)
nur einmal und in der Klasse speichern und so weiter ...
Ich denke, Sie müssen etwas zusätzlichen Code schreiben. Beispielsweise:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
In diesem Fall erstellen wir eine neue Liste mit allen Einträgen in USERNAMES
, die in Großbuchstaben umgewandelt wurden, und vergleichen sie dann mit dieser neuen Liste.
Update
Wie @ viraptor sagt, ist es sogar besser, einen Generator anstelle von map
zu verwenden. Siehe @ Nathon 's Antwort .
Hier ist eine Möglichkeit:
if string1.lower() in string2.lower():
...
Damit dies funktioniert, müssen sowohl string1
und string2
Objekte müssen vom Typ string
sein.
str.casefold
Wird für einen String-Abgleich empfohlen, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird. @ nmichaels's Lösung kann trivial angepasst werden.
Benutze das eine oder das andere:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Oder:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
Gemäß docs :
Casefolding ähnelt Lowercasing, ist jedoch aggressiver, da alle Fallunterscheidungen in einer Zeichenfolge entfernt werden sollen. Zum Beispiel ist der deutsche Kleinbuchstabe "ß" gleichbedeutend mit "ss". Da es sich bereits um Kleinbuchstaben handelt, würde
lower()
nichts gegen 'ß' unternehmen.casefold()
konvertiert es in "ss".
Du könntest es tun
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
Update: ein bisschen rumgespielt und ich denke man könnte einen besseren Kurzschlussansatz mit bekommen
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
Die Funktion ifilter
stammt aus itertools, einem meiner Lieblingsmodule in Python. Es ist schneller als ein Generator, erstellt jedoch nur dann das nächste Element der Liste, wenn es aufgerufen wird.
Meine 5 (falschen) Cent
'a' in "" .join (['A']). lower ()
Autsch, stimme voll und ganz @jpp zu, ich behalte als Beispiel für schlechte Praxis :(