Como posso fazer comparação de strings sem distinção entre maiúsculas e minúsculas no Python?
Gostaria de encapsular a comparação de cadeias regulares a uma cadeia de repositórios usando de uma maneira muito simples e Python. Eu também gostaria de ter a capacidade de procurar valores em um dict hash por strings usando strings python regulares.
python
comparison
case-insensitive
Kozyarchuk
fonte
fonte
Σίσυφος
eΣΊΣΥΦΟΣ
, então, sua abordagem falha, porque essas devem ser o mesmo caso sem sensibilidade.'ß'.lower() == 'SS'.lower()
é falso.Comparar strings de uma maneira que não diferencia maiúsculas de minúsculas parece trivial, mas não é. Eu vou usar o Python 3, pois o Python 2 é subdesenvolvido aqui.
A primeira coisa a observar é que as conversões de remoção de maiúsculas e minúsculas no Unicode não são triviais. Há texto para o qual
text.lower() != text.upper().lower()
, como"ß"
:Mas digamos que você queria comparar
"BUSSE"
e"Buße"
. Caramba, você provavelmente também quer comparar"BUSSE"
e"BUẞE"
igualar - essa é a nova forma de capital. A maneira recomendada é usarcasefold
:Não use apenas
lower
. Secasefold
não estiver disponível, fazer.upper().lower()
ajuda (mas apenas um pouco).Então você deve considerar sotaques. Se o seu renderizador de fontes é bom, você provavelmente pensa
"ê" == "ê"
- mas não:Isso ocorre porque o sotaque desse último é um personagem combinado.
A maneira mais simples de lidar com isso é
unicodedata.normalize
. Você provavelmente deseja usar a normalização do NFKD , mas fique à vontade para verificar a documentação. Então se fazPara finalizar, aqui isso é expresso em funções:
fonte
x.casefold() == y.casefold()
comparações que não diferenciam maiúsculas de minúsculas (e, mais importante, quex == y
diferenciam maiúsculas de minúsculas).NFD(toCasefold(NFD(str)))
em ambos os lados e (D147, compatibilidade)NFKD(toCasefold(NFKD(toCasefold(NFD(X)))))
em ambos os lados. Ele afirma que o interiorNFD
é apenas para lidar com um certo caráter de sotaque grego. Eu acho que é tudo sobre os casos extremos.Usando Python 2, chamando
.lower()
cada string ou objeto Unicode ...... funcionará a maior parte do tempo, mas na verdade não funciona nas situações descritas por tchrist .
Suponha que temos um arquivo chamado
unicode.txt
contendo as duas stringsΣίσυφος
eΣΊΣΥΦΟΣ
. Com o Python 2:O caractere has possui duas formas minúsculas, ς e σ, e
.lower()
não ajudará a compará-las sem distinção entre maiúsculas e minúsculas.No entanto, a partir do Python 3, todos os três formulários serão resolvidos como ς, e chamar lower () em ambas as strings funcionará corretamente:
Portanto, se você se importa com casos extremos como os três sigmas em grego, use Python 3.
(Para referência, Python 2.7.3 e Python 3.3.0b1 são mostrados nas impressões do interpretador acima.)
fonte
A Seção 3.13 do padrão Unicode define algoritmos para correspondência sem caixa.
X.casefold() == Y.casefold()
no Python 3 implementa a "correspondência padrão sem caixa" (D144).Casefolding não preserva a normalização de strings em todas as instâncias e, portanto, a normalização precisa ser feita (
'å'
vs.'å'
). O D145 apresenta a "correspondência canônica sem caixa":NFD()
é chamado duas vezes para casos de borda muito pouco frequentes envolvendo o caractere U + 0345.Exemplo:
Também há compatibilidade sem caixa de compatibilidade (D146) para casos como
'㎒'
(U + 3392) e "correspondência sem caixa de identificador" para simplificar e otimizar a correspondência sem caixa de identificadores .fonte
casefold()
função não implementa o tratamento especial de maiúsculas I e maiúsculas pontilhadas I, conforme descrito em Case Folding Properties . Portanto, a comparação pode falhar para palavras de idiomas turcos que contenham essas letras. Por exemplo,canonical_caseless('LİMANI') == canonical_caseless('limanı')
deve retornarTrue
, mas retornaFalse
. Atualmente, a única maneira de lidar com isso no Python é escrever um wrapper de casefold ou usar uma biblioteca Unicode externa, como PyICU.Eu vi essa solução aqui usando regex .
Funciona bem com sotaques
No entanto, ele não funciona com caracteres unicode que não diferenciam maiúsculas de minúsculas. Obrigado @Rhymoid por apontar que, como eu entendi, ele precisa do símbolo exato, para que o caso seja verdadeiro. A saída é a seguinte:
fonte
ß
não é encontrado dentroSS
com busca case-insensitive evidências de que ele não funciona o trabalho com caracteres Unicode em tudo .A abordagem usual é colocar as cadeias em maiúsculas ou minúsculas para as pesquisas e comparações. Por exemplo:
fonte
Que tal converter primeiro para minúsculas? você pode usar
string.lower()
.fonte
Σίσυφος
eΣΊΣΥΦΟΣ
não testaria equivalente, mas deveria.fonte
Tudo o que você precisa fazer é converter as duas strings em minúsculas (todas as letras se tornam minúsculas) e depois compará-las (assumindo que as strings sejam ASCII).
Por exemplo:
fonte
Este é outro regex que aprendi a amar / odiar na última semana, então geralmente importo como (neste caso, sim) algo que reflete como estou me sentindo! faça uma função normal .... solicite entrada e use .... algo = re.compile (r'foo * | spam * ', yes.I) ...... re.I (yes.I abaixo) é o mesmo que IGNORECASE, mas você não pode cometer tantos erros ao escrevê-lo!
Em seguida, você pesquisa sua mensagem usando regex, mas honestamente isso deve ter algumas páginas, mas o ponto é que foo ou spam são canalizados juntos e a caixa é ignorada. Então, se um deles for encontrado, lost_n_found exibirá um deles. se nenhum deles, lost_n_found for igual a None. Se não for igual a nenhum, retorne o user_input em letras minúsculas usando "return lost_n_found.lower ()"
Isso permite que você combine com mais facilidade qualquer coisa que diferencia maiúsculas de minúsculas. Por fim (NCS), significa "ninguém se importa seriamente ...!" ou não diferencia maiúsculas de minúsculas ...
se alguém tiver alguma dúvida me fale sobre isso ..
fonte