Wie kann ich in Python einen Vergleich von Zeichenfolgen ohne Berücksichtigung der Groß- und Kleinschreibung durchführen?
Ich möchte den Vergleich einer regulären Zeichenfolge mit einer Repository-Zeichenfolge auf sehr einfache und pythonische Weise zusammenfassen. Ich möchte auch die Möglichkeit haben, Werte in einem Diktat nachzuschlagen, das von Zeichenfolgen mit regulären Python-Zeichenfolgen gehasht wird.
python
comparison
case-insensitive
Kozyarchuk
quelle
quelle
Σίσυφος
und sindΣΊΣΥΦΟΣ
, schlägt Ihr Ansatz fehl, da diese unempfindlich der gleiche Fall sein sollen.'ß'.lower() == 'SS'.lower()
ist falsch.Der Vergleich von Zeichenfolgen auf eine Weise, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird, scheint trivial zu sein, ist es aber nicht. Ich werde Python 3 verwenden, da Python 2 hier unterentwickelt ist.
Das erste, was zu beachten ist, ist, dass das Entfernen von Groß- und Kleinschreibung in Unicode nicht trivial ist. Es gibt Text, für den
text.lower() != text.upper().lower()
wie"ß"
:Aber lassen Sie uns sagen , Sie zu caselessly vergleichen wollte
"BUSSE"
und"Buße"
. Heck, Sie möchten wahrscheinlich auch vergleichen"BUSSE"
und"BUẞE"
gleich - das ist die neuere Kapitalform. Der empfohlene Weg istcasefold
:Nicht nur verwenden
lower
. Wenncasefold
nicht verfügbar,.upper().lower()
hilft das Tun (aber nur etwas).Dann sollten Sie Akzente berücksichtigen. Wenn Ihr Font-Renderer gut ist, denken Sie wahrscheinlich
"ê" == "ê"
- aber nicht:Dies liegt daran, dass der Akzent auf letzterem ein kombinierender Charakter ist.
Der einfachste Weg, damit umzugehen, ist
unicodedata.normalize
. Sie möchten wahrscheinlich die NFKD- Normalisierung verwenden , können jedoch die Dokumentation überprüfen. Dann tut man esZum Schluss wird dies hier in Funktionen ausgedrückt:
quelle
x.casefold() == y.casefold()
Vergleiche durchführen,x == y
bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird (und vor allem Groß- und Kleinschreibung beachten).NFD(toCasefold(NFD(str)))
Gehäuse : (D146, kanonisch) auf beiden Seiten und (D147, Kompatibilität)NFKD(toCasefold(NFKD(toCasefold(NFD(X)))))
auf beiden Seiten. Es heißt, dass das InnereNFD
ausschließlich mit einem bestimmten griechischen Akzentcharakter zu tun hat. Ich denke, es geht nur um die Randfälle.Rufen Sie mit Python 2
.lower()
jede Zeichenfolge oder jedes Unicode-Objekt auf ...... wird die meiste Zeit funktionieren, funktioniert aber in den von @tchrist beschriebenen Situationen nicht .
Angenommen, wir haben eine Datei
unicode.txt
mit den beiden ZeichenfolgenΣίσυφος
undΣΊΣΥΦΟΣ
. Mit Python 2:Das Σ-Zeichen hat zwei Kleinbuchstaben, ς und σ, und
.lower()
hilft nicht, sie ohne Berücksichtigung der Groß- und Kleinschreibung zu vergleichen.Ab Python 3 werden jedoch alle drei Formulare in ς aufgelöst, und das Aufrufen von lower () für beide Zeichenfolgen funktioniert ordnungsgemäß:
Wenn Sie sich also für Randfälle wie die drei griechischen Sigmen interessieren, verwenden Sie Python 3.
(Als Referenz werden Python 2.7.3 und Python 3.3.0b1 in den obigen Interpreter-Ausdrucken gezeigt.)
quelle
In Abschnitt 3.13 des Unicode-Standards werden Algorithmen für das Caseless Matching definiert.
X.casefold() == Y.casefold()
implementiert in Python 3 das "Standard-Caseless-Matching" (D144).Beim Fallfalten bleibt die Normalisierung von Zeichenfolgen nicht in allen Fällen erhalten, und daher muss die Normalisierung durchgeführt werden (
'å'
vs.'å'
). D145 führt "Canonical Caseless Matching" ein:NFD()
wird zweimal für sehr seltene Randfälle mit U + 0345-Zeichen aufgerufen.Beispiel:
Es gibt auch Kompatibilitäts-Caseless-Matching (D146) für Fälle wie
'㎒'
(U + 3392) und "Identifier Caseless Matching", um das Caseless-Matching von Identifikatoren zu vereinfachen und zu optimieren .quelle
casefold()
nicht Funktion nicht die spezielle Fall der Behandlung von Groß I implementieren und punktierte Groß I , wie in beschriebenem Fall Folding Eigenschaften . Daher kann der Vergleich für Wörter aus türkischen Sprachen, die diese Buchstaben enthalten, fehlschlagen. Zum Beispielcanonical_caseless('LİMANI') == canonical_caseless('limanı')
muss zurückkehrenTrue
, aber es gibt zurückFalse
. Derzeit besteht die einzige Möglichkeit, in Python damit umzugehen, darin, einen Casefold-Wrapper zu schreiben oder eine externe Unicode-Bibliothek wie PyICU zu verwenden.Ich habe diese Lösung hier mit Regex gesehen .
Es funktioniert gut mit Akzenten
Bei Unicode-Zeichen, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird, funktioniert dies jedoch nicht. Vielen Dank an @Rhymoid, dass Sie darauf hingewiesen haben, dass nach meinem Verständnis das genaue Symbol erforderlich ist, damit der Fall wahr ist. Die Ausgabe ist wie folgt:
quelle
ß
nicht innerhalb gefunden wirdSS
mit Groß- und Kleinschreibung Suche gibt Hinweise darauf , dass es nicht funktioniert die Arbeit mit Unicode - Zeichen überhaupt .Der übliche Ansatz besteht darin, die Zeichenfolgen für die Suche und Vergleiche in Groß- oder Kleinbuchstaben zu schreiben. Zum Beispiel:
quelle
Wie wäre es zuerst mit der Konvertierung in Kleinbuchstaben? Sie können verwenden
string.lower()
.quelle
Σίσυφος
undΣΊΣΥΦΟΣ
würden kein Äquivalent testen, sollten es aber.quelle
Alles, was Sie tun müssen, ist, die beiden Zeichenfolgen in Kleinbuchstaben umzuwandeln (alle Buchstaben werden zu Kleinbuchstaben) und sie dann zu vergleichen (vorausgesetzt, die Zeichenfolgen sind ASCII-Zeichenfolgen).
Zum Beispiel:
quelle
Dies ist eine weitere Regex, die ich in der letzten Woche lieben / hassen gelernt habe, also normalerweise als (in diesem Fall ja) etwas importieren, das widerspiegelt, wie ich mich fühle! mache eine normale Funktion .... frage nach Eingabe, dann benutze .... etwas = re.compile (r'foo * | spam * ', yes.I) ...... re.I (yes.I unten) ist dasselbe wie IGNORECASE, aber Sie können nicht so viele Fehler machen, wenn Sie es schreiben!
Sie durchsuchen Ihre Nachricht dann mit regulären Ausdrücken, aber ehrlich gesagt sollten dies einige Seiten sein, aber der Punkt ist, dass Foo oder Spam zusammengeleitet werden und Groß- und Kleinschreibung ignoriert wird. Wenn dann einer von beiden gefunden wird, zeigt lost_n_found einen von ihnen an. Wenn beides nicht der Fall ist, ist lost_n_found gleich None. Wenn es nicht gleich none ist, geben Sie den user_input in Kleinbuchstaben mit "return lost_n_found.lower ()" zurück.
Auf diese Weise können Sie alles, was zwischen Groß- und Kleinschreibung unterscheidet, viel einfacher abgleichen. Schließlich steht (NCS) für "niemand kümmert sich ernsthaft ...!" oder nicht zwischen Groß- und Kleinschreibung unterscheiden .... je nachdem
Wenn jemand irgendwelche Fragen hat, melde dich bei mir.
quelle