Как мне выполнить сравнение строк без учета регистра?
Как я могу сравнивать строки в Python без учета регистра?
Я хотел бы инкапсулировать сравнение обычных строк со строкой репозитория, используя простой код на Pythonic. Я также хотел бы иметь возможность искать значения в dict, хэшированном строками, используя обычные строки python.
Переведено автоматически
Ответ 1
Предполагается, что строки ASCII:
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)")
Начиная с Python 3.3, casefold() является лучшей альтернативой:
string1 = 'Hello' string2 = 'hello'
if string1.casefold() == string2.casefold(): print("The strings are the same (case insensitive)") else: print("The strings are NOT the same (case insensitive)")
Если вам нужно более комплексное решение, которое обрабатывает более сложные сравнения в юникоде, посмотрите Другие ответы.
Ответ 2
Сравнение строк без учета регистра кажется тривиальным, но это не так. Я буду использовать Python 3, поскольку Python 2 здесь недостаточно развит.
Первое, на что следует обратить внимание, это то, что преобразования с удалением регистра в Unicode не являются тривиальными. Есть текст, для которого text.lower() != text.upper().lower(), например "ß":
>>> "ß".lower() 'ß' >>> "ß".upper().lower() 'ss'
Но допустим, вы хотели сравнить без регистра "BUSSE" и "Buße". Черт возьми, вы, вероятно, также хотите сравнить "BUSSE" и "BUẞE" equal - это более новая заглавная форма. Рекомендуемый способ - использовать casefold:
str.casefold()
Возвращает копию строки с заглавной буквой. Строки с заглавной буквой могут использоваться для сопоставления без заглавной буквы.
Преобразование в регистр символов похоже на использование нижнего регистра, но более агрессивно, поскольку предназначено для удаления всех различий в регистре в строке. [...]
Не используйте просто lower. Если casefold недоступен, выполнение .upper().lower() помогает (но лишь отчасти).
Тогда вам следует подумать о акцентах. Если ваш рендеринг шрифтов хорош, вы, вероятно, думаете "ê" == "ê" - но это не так:
>>> "ê" == "ê" 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 нормализацию, но не стесняйтесь ознакомиться с документацией. Затем выполняется
X.casefold() == Y.casefold() в Python 3 реализовано "сопоставление без регистра по умолчанию" (D144).
Разбиение на регистры не сохраняет нормализацию строк во всех экземплярах, и поэтому нормализацию необходимо выполнить ('å' против 'å'). D145 вводит "каноническое сопоставление без регистра":
Также существуют функции сопоставления без регистра совместимости (D146) для таких случаев, как '㎒' (U + 3392) и "сопоставление без регистра идентификаторов" для упрощения и оптимизации сопоставления идентификаторов без регистра.