Hoe maak ik een hoofdletterongevoelige tekenreeksvergelijking?

Hoe kan ik hoofdletterongevoelige tekenreeksen vergelijken in Python?

Ik wil graag de vergelijking van een reguliere string met een repository-string op een zeer eenvoudige en Pythonische manier inkapselen. Ik zou ook graag de mogelijkheid willen hebben om waarden op te zoeken in een dictaat dat is gehasht door strings met behulp van gewone python-strings.


Antwoord 1, autoriteit 100%

Ervan uitgaande dat ASCII-tekenreeksen:

string1 = 'Hello'
string2 = 'hello'
if string1.lower() == string2.lower():
    print("The strings are the same (case insensitive)")
else:
    print("The strings are NOT the same (case insensitive)")

Antwoord 2, autoriteit 94%

Het vergelijken van strings op een niet-hoofdlettergevoelige manier lijkt triviaal, maar is het niet. Ik zal Python 3 gebruiken, omdat Python 2 hier onderontwikkeld is.

Het eerste dat moet worden opgemerkt, is dat het verwijderen van hoofdletters in Unicode niet triviaal is. Er is tekst waarvoor text.lower() != text.upper().lower(), zoals "?":

"?".lower()
#>>> '?'
"?".upper().lower()
#>>> 'ss'

Maar laten we zeggen dat je "BUSSE"en "BU?E"zonder hoofdletters wilt vergelijken. Heck, je wilt waarschijnlijk ook "BUSSE"en "BU?E"gelijk vergelijken – dat is de nieuwere hoofdletter. De aanbevolen manier is om casefold:

str.casefold()

Retourneer een opgevouwen kopie van de tekenreeks. Casefolded snaren kunnen worden gebruikt voor:
matchen zonder hoofdletters.

Casefolding lijkt op kleine letters, maar is agressiever omdat het dat is
bedoeld om alle onderscheidingen tussen hoofdletters in een string te verwijderen. […]

Gebruik niet alleen lower. Als casefoldniet beschikbaar is, helpt het om .upper().lower()te doen (maar slechts in beperkte mate).

Dan moet je rekening houden met accenten. Als uw lettertype-renderer goed is, denkt u waarschijnlijk "e" == "e?"– maar dat is niet zo:

"e" == "e?"
#>>> False

Dit komt omdat het accent op de laatste een combinatiekarakter is.

import unicodedata
[unicodedata.name(char) for char in "e"]
#>>> ['LATIN SMALL LETTER E WITH CIRCUMFLEX']
[unicodedata.name(char) for char in "e?"]
#>>> ['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']

De eenvoudigste manier om hiermee om te gaan is unicodedata.normalize. Je wilt waarschijnlijk NFKDnormalisatiegebruiken, maar voel je vrij om de documentatie te controleren. Dan doet men dat wel

unicodedata.normalize("NFKD", "e") == unicodedata.normalize("NFKD", "e?")
#>>> True

Om af te ronden, hier wordt dit uitgedrukt in functies:

import unicodedata
def normalize_caseless(text):
    return unicodedata.normalize("NFKD", text.casefold())
def caseless_equal(left, right):
    return normalize_caseless(left) == normalize_caseless(right)

Antwoord 3, autoriteit 10%

Python 2 gebruiken, .lower()aanroepen voor elke string of Unicode-object…

string1.lower() == string2.lower()

…zal meestal werken, maar werkt inderdaad niet in de situaties die @tchrist heeft beschreven.

Stel dat we een bestand hebben met de naam unicode.txtmet daarin de twee strings ???????en ???????. Met Python 2:

>>> utf8_bytes = open("unicode.txt", 'r').read()
>>> print repr(utf8_bytes)
'\xce\xa3\xce\xaf\xcf\x83\xcf\x85\xcf\x86\xce\xbf\xcf\x82\n\xce\xa3\xce\x8a\xce\xa3\xce\xa5\xce\xa6\xce\x9f\xce\xa3\n'
>>> u = utf8_bytes.decode('utf8')
>>> print u
???????
???????
>>> first, second = u.splitlines()
>>> print first.lower()
???????
>>> print second.lower()
???????
>>> first.lower() == second.lower()
False
>>> first.upper() == second.upper()
True

De ? karakter heeft twee kleine letters, ? en ?, en .lower()helpen niet om ze hoofdletterongevoelig te vergelijken.

Vanaf Python 3 zullen echter alle drie de vormen worden omgezet in ?, en het aanroepen van lower() op beide strings zal correct werken:

>>> s = open('unicode.txt', encoding='utf8').read()
>>> print(s)
???????
???????
>>> first, second = s.splitlines()
>>> print(first.lower())
???????
>>> print(second.lower())
???????
>>> first.lower() == second.lower()
True
>>> first.upper() == second.upper()
True

Dus als je om randgevallen geeft, zoals de drie sigma’s in het Grieks, gebruik dan Python 3.

(Ter referentie, Python 2.7.3 en Python 3.3.0b1 worden getoond in de tolk-afdrukken hierboven.)


Antwoord 4, autoriteit 7%

Sectie 3.13 van de Unicode-standaarddefinieert algoritmen voor
overeenkomend.

X.casefold() == Y.casefold()in Python 3 implementeert de “standaard caseless matching” (D144).

Casefolding behoudt de normalisatie van strings niet in alle gevallen en daarom moet de normalisatie worden uitgevoerd ('a'vs. 'a?'). D145 introduceert “canonieke matching zonder hoofdletters”:

import unicodedata
def NFD(text):
    return unicodedata.normalize('NFD', text)
def canonical_caseless(text):
    return NFD(NFD(text).casefold())

NFD()wordt twee keer aangeroepen voor zeer zeldzame randgevallen met U+0345-tekens.

Voorbeeld:

>>> 'a'.casefold() == 'a?'.casefold()
False
>>> canonical_caseless('a') == canonical_caseless('a?')
True

Er zijn ook compatibiliteitsvergelijkingen zonder hoofdletters (D146) voor gevallen zoals '?'(U+3392) en “identificatieletters zonder hoofdletters” om identificatie zonder hoofdletters.


Antwoord 5

Ik zag deze oplossing hier met behulp van regex.

import re
if re.search('mandy', 'Mandy Pande', re.IGNORECASE):
# is True

Het werkt goed met accenten

In [42]: if re.search("e","e", re.IGNORECASE):
....:        print(1)
....:
1

Het werkt echter niet met unicode-tekens die niet hoofdlettergevoelig zijn. Bedankt @Rhymoid om erop te wijzen dat, zoals ik begreep, het exacte symbool nodig is om de zaak waar te maken. De uitvoer is als volgt:

In [36]: "?".lower()
Out[36]: '?'
In [37]: "?".upper()
Out[37]: 'SS'
In [38]: "?".upper().lower()
Out[38]: 'ss'
In [39]: if re.search("?","??", re.IGNORECASE):
....:        print(1)
....:
1
In [40]: if re.search("SS","??", re.IGNORECASE):
....:        print(1)
....:
In [41]: if re.search("?","SS", re.IGNORECASE):
....:        print(1)
....:

Antwoord 6

U kunt de methode casefold() gebruiken. De methode casefold() negeert gevallen bij het vergelijken.

firstString = "Hi EVERYONE"
secondString = "Hi everyone"
if firstString.casefold() == secondString.casefold():
    print('The strings are equal.')
else:
    print('The strings are not equal.')

Uitvoer:

The strings are equal.

Antwoord 7

De gebruikelijke aanpak is om de tekenreeksen in hoofdletters of in kleine letters te gebruiken voor het opzoeken en vergelijken. Bijvoorbeeld:

>>> "hello".upper() == "HELLO".upper()
True
>>> 

Antwoord 8

Wat dacht je ervan om eerst naar kleine letters te converteren? je kunt string.lower()gebruiken.


Antwoord 9

U kunt case=Falsevermelden in de str.contains()

data['Column_name'].str.contains('abcd', case=False)

Antwoord 10

def insenStringCompare(s1, s2):
    """ Method that takes two strings and returns True or False, based
        on if they are equal, regardless of case."""
    try:
        return s1.lower() == s2.lower()
    except AttributeError:
        print "Please only pass strings into this method."
        print "You passed a %s and %s" % (s1.__class__, s2.__class__)

Antwoord 11

Dit is een andere regex die ik de afgelopen week heb leren liefhebben / haten, dus importeer ze meestal als (in dit geval ja) iets dat weerspiegelt hoe ik me voel!
maak een normale functie…. vraag om invoer, gebruik dan ….something = re.compile(r’foo*|spam*’, yes.I)…… re.I (yes.I hieronder) is hetzelfde als IGNORECASE, maar je kunt niet zoveel fouten maken als je het schrijft!

Je doorzoekt dan je bericht met behulp van regex’s, maar eerlijk gezegd zou dat een paar pagina’s op zich moeten zijn, maar het punt is dat foo of spam samen worden doorgesluisd en hoofdletters worden genegeerd.
Als een van beide wordt gevonden, zal lost_n_found er een weergeven. indien geen van beide, dan is lost_n_found gelijk aan Geen. Als het niet gelijk is aan geen, retourneer je de user_input in kleine letters met “return lost_n_found.lower()”

Hierdoor kunt u veel gemakkelijker alles matchen dat hoofdlettergevoelig is. Ten slotte staat (NCS) voor “no one cares serious…!” of niet hoofdlettergevoelig….wat dan ook

Als iemand vragen heeft, laat het me weten..

   import re as yes
    def bar_or_spam():
        message = raw_input("\nEnter FoO for BaR or SpaM for EgGs (NCS): ") 
        message_in_coconut = yes.compile(r'foo*|spam*',  yes.I)
        lost_n_found = message_in_coconut.search(message).group()
        if lost_n_found != None:
            return lost_n_found.lower()
        else:
            print ("Make tea not love")
            return
    whatz_for_breakfast = bar_or_spam()
    if whatz_for_breakfast == foo:
        print ("BaR")
    elif whatz_for_breakfast == spam:
        print ("EgGs")

LEAVE A REPLY

Please enter your comment!
Please enter your name here

two × five =

Other episodes