Как я могу сделать сравнение строк без учета регистра в Python?
Я хотел бы инкапсулировать сравнение обычной строки со строкой репозитория, используя очень простой и Pythonic способ. Я также хотел бы иметь возможность искать значения в dict, хэшированном строками, используя обычные строки python.
python
comparison
case-insensitive
Kozyarchuk
источник
источник
Σίσυφος
иΣΊΣΥΦΟΣ
, тогда ваш подход потерпит неудачу, потому что они должны быть одинаковыми без учета регистра.'ß'.lower() == 'SS'.lower()
ложно.Сравнение строк без учета регистра кажется тривиальным, но это не так. Я буду использовать Python 3, так как Python 2 здесь недостаточно развит.
Первое, на что нужно обратить внимание, - это то, что преобразования с удалением регистра в Unicode не являются тривиальными. Есть текст, для которого
text.lower() != text.upper().lower()
, например"ß"
:Но, допустим, вы хотели безошибочно сравнить
"BUSSE"
и"Buße"
. Черт возьми, вы, вероятно, тоже хотите сравнить"BUSSE"
и сравнить"BUẞE"
- это более новая форма капитала. Рекомендуемый способ заключается в использованииcasefold
:Не просто использовать
lower
. Еслиcasefold
нет в наличии, делаю.upper().lower()
помогает (но только в некоторой степени).Тогда вы должны рассмотреть акценты. Если ваш рендерер шрифтов хорош, вы, вероятно, думаете,
"ê" == "ê"
но это не так:Это потому, что акцент на последнем является сочетанием характера.
Самый простой способ справиться с этим
unicodedata.normalize
. Вы, вероятно, хотите использовать нормализацию NFKD , но не стесняйтесь проверять документацию. Тогда одинЧтобы закончить, здесь это выражается в функциях:
источник
x.casefold() == y.casefold()
сравнение без учета регистра (и, что более важно,x == y
с учетом регистра).NFD(toCasefold(NFD(str)))
с обеих сторон и (D147, совместимость)NFKD(toCasefold(NFKD(toCasefold(NFD(X)))))
с обеих сторон. В нем говорится, что внутреннееNFD
исключительно для обработки определенного греческого символа акцента. Я думаю, это все о крайних случаях.Используя Python 2, вызывая
.lower()
каждую строку или объект Unicode ...... будет работать большую часть времени, но на самом деле не работает в ситуациях, описанных @tchrist .
Предположим, у нас есть файл с именем,
unicode.txt
содержащий две строкиΣίσυφος
иΣΊΣΥΦΟΣ
. С Python 2:Символ Σ имеет две строчные формы, ς и σ, и
.lower()
не поможет сравнить их без учета регистра.Однако, начиная с Python 3, все три формы будут преобразованы в ς, и вызов метода lower () для обеих строк будет работать правильно:
Так что если вы заботитесь о крайних случаях, таких как три сигмы на греческом языке, используйте Python 3.
(Для справки, Python 2.7.3 и Python 3.3.0b1 показаны в распечатках интерпретатора выше.)
источник
Раздел 3.13 стандарта Unicode определяет алгоритмы для сопоставления без учета регистра.
X.casefold() == Y.casefold()
в Python 3 реализуется «сопоставление без учета регистра по умолчанию» (D144).Завершение кейса не сохраняет нормализацию строк во всех случаях, и поэтому нормализация должна быть выполнена (
'å'
против'å'
). D145 вводит "каноническое сопоставление без регистра":NFD()
вызывается дважды для очень редких краевых случаев с участием символа U + 0345.Пример:
Также есть сопоставление без учета регистра (D146) для таких случаев, как
'㎒'
(U + 3392) и « сопоставление без учета идентификатора», чтобы упростить и оптимизировать сопоставление без учета идентификаторов .источник
casefold()
функция не реализует специальную обработку регистра прописных букв I и прописных букв I, как описано в разделе Свойства сворачивания регистра . Поэтому сравнение может быть неудачным для слов из тюркских языков, содержащих эти буквы. Например,canonical_caseless('LİMANI') == canonical_caseless('limanı')
должен вернутьсяTrue
, но он возвращаетсяFalse
. В настоящее время единственный способ справиться с этим в Python - написать оболочку casefold или использовать внешнюю библиотеку Unicode, такую как PyICU.Я видел это решение здесь с помощью регулярных выражений .
Хорошо работает с акцентами
Однако он не работает с символами Юникода без учета регистра. Спасибо @Rhymoid за указание на то, что, насколько я понимаю, ему нужен точный символ, чтобы случай был правдой. Вывод следующий:
источник
ß
не найден вSS
с нечувствительным к регистру поиска является доказательством того, что он не работает работу с символами Unicode на всех .Обычный подход состоит в том, чтобы прописать строчные или строчные буквы для поиска и сравнения. Например:
источник
Как насчет преобразования в нижний регистр в первую очередь? Вы можете использовать
string.lower()
.источник
Σίσυφος
иΣΊΣΥΦΟΣ
не проверяли бы эквивалент, но должны.источник
Все, что вам нужно сделать, это преобразовать две строки в строчные (все буквы становятся строчными), а затем сравнить их (предполагая, что строки являются строками ASCII).
Например:
источник
Это еще одно регулярное выражение, которое я научился любить / ненавидеть на прошлой неделе, поэтому обычно придаю значение (в данном случае да) тому, что отражает мои чувства! сделать нормальную функцию .... запросить ввод, затем использовать .... что-то = re.compile (r'foo * | spam * ', yes.I) ...... re.I (yes.I ниже) - то же самое, что IGNORECASE, но вы не можете совершить столько ошибок при написании!
Затем вы ищите свое сообщение с помощью регулярных выражений, но, честно говоря, это должно быть несколько отдельных страниц, но дело в том, что foo или spam передаются вместе, а case игнорируется. Затем, если любой из них найден, lost_n_found отобразит один из них. если ни то, ни другое lost_n_found равно None. Если оно не равно ни одному, верните user_input в нижнем регистре, используя «return lost_n_found.lower ()»
Это позволяет вам намного легче сопоставить все, что будет чувствительно к регистру. Наконец (NCS) означает "никто не заботится серьезно ...!" или не чувствительны к регистру .... какой бы ни
если у кого-то есть какие-либо вопросы, дайте мне знать об этом ..
источник