Сравнение строки без учета регистра кажется чем-то тривиальным, но это не так. Я буду использовать Python 3, так как Python 2 здесь недостаточно развит.
Первое, на что нужно обратить внимание, это то, что конверсии с удалением регистра в юникоде не тривиальны. Есть текст, для которого text.lower() != text.upper().lower()
, например, "ß"
:
"ß".lower()
#>>> 'ß'
"ß".upper().lower()
#>>> 'ss'
Но предположим, что вы хотели сравнить без учета "BUSSE"
и "Buße"
. Черт возьми, вы, вероятно, также хотите сравнить "BUSSE"
и "BUẞE"
равных - это более новая форма капитала. Рекомендуемый способ - использовать casefold
:
.
help(str.casefold)
#>>> Help on method_descriptor:
#>>>
#>>> casefold(...)
#>>> S.casefold() -> str
#>>>
#>>> Return a version of S suitable for caseless comparisons.
#>>>
Не просто используйте lower
. Если casefold
недоступен, 363638674 помогает (но только в некоторой степени).
Тогда вы должны рассмотреть акценты. Если ваш рендерер шрифтов хорош, вы, вероятно, думаете "ê" == "ê"
- но это не так:
"ê" == "ê"
#>>> False
Это потому, что они на самом деле
import unicodedata
[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E WITH CIRCUMFLEX']
[unicodedata.name(char) for char in "ê"]
#>>> ['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']
Самый простой способ справиться с этим - unicodedata.normalize
. Возможно, вы хотите использовать NFKD для нормализации, но не стесняйтесь проверять документацию. Затем один делает
unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
#>>> True
Чтобы закончить, здесь это выражается в функциях:
import unicodedata
def normalize_caseless(text):
return unicodedata.normalize("NFKD", text.casefold())
def caseless_equal(left, right):
return normalize_caseless(left) == normalize_caseless(right)