Должен ли я использовать Python casefold?
Недавно читал о casefold и сравнениях строк при игнорировании регистра. Я читал, что стандарт MSDN должен использовать InvariantCulture и определенно избегать использования нижнего регистра. Тем не менее, casefold из того, что я прочитал, похоже на более агрессивный к нижнему регистру. Мой вопрос должен ли я использовать casefold в Python или есть вместо этого более питонический стандарт? Кроме того, casefold проходит Тест Турции?
1 ответ
1) В Python 3 casefold()
должен использоваться для реализации сопоставления строк без учета регистра.
Начиная с Python 3.0, строки хранятся как Unicode. Стандарт 3.13 стандарта Unicode определяет сопоставление без учета регистра по умолчанию следующим образом:
Строка X является регистром совпадения для строки Y тогда и только тогда, когда:
toCasefold (X) = toCasefold (Y)
Питона casefold()
реализует Юникод toCasefold()
, Поэтому его следует использовать для реализации сопоставления строк без учета регистра. Хотя одних только случаев недостаточно, чтобы покрыть некоторые угловые случаи и пройти тест Турции (см. Пункт 3).
2) Начиная с Python 3.6, casefold() не может пройти тест Турции.
Для двух символов, прописных букв I и точечных прописных букв I, стандарт Unicode определяет два разных сопоставления регистров.
По умолчанию (для нетюркских языков):
I → i (U + 0049 → U + 0069)
İ → i̇ (U + 0130 → U + 0069 U + 0307)
Альтернатива (для тюркских языков):
I → ı (U + 0049 → U + 0131)
İ → i (U + 0130 → U + 0069)
Питоны casefold()
может применять только сопоставление по умолчанию и не проходит тест Турции. Например, турецкие слова "LİMANI" и "limanı" являются безусловными эквивалентами, но "LİMANI".casefold() == "limanı".casefold()
возвращается False
, Нет возможности включить альтернативное сопоставление.
3) Как выполнить поиск без учета регистра в Python 3.
Стандарт 3.13 стандарта Unicode описывает несколько алгоритмов сопоставления без учета регистра. Каноническое сопоставление без учета, вероятно, подойдет для большинства случаев использования. Этот алгоритм уже учитывает все угловые случаи. Нам нужно только добавить опцию для переключения между нетюркскими и тюркскими делами.
import unicodedata
def normalize_NFD(string):
return unicodedata.normalize('NFD', string)
def casefold_(string, include_special_i=False):
if include_special_i:
string = unicodedata.normalize('NFC', string)
string = string.replace('\u0049', '\u0131')
string = string.replace('\u0130', '\u0069')
return string.casefold()
def casefold_NFD(string, include_special_i=False):
return normalize_NFD(casefold_(normalize_NFD(string), include_special_i))
def caseless_match(string1, string2, include_special_i=False):
return casefold_NFD(string1, include_special_i) == casefold_NFD(string2, include_special_i)
casefold_()
это обертка для Python casefold()
, Если его параметр include_special_i
установлен в True
затем применяется тюркское отображение, и если оно установлено на False
используется сопоставление по умолчанию.
caseless_match()
каноническое совпадение string1
а также string2
, Если строки являются тюркскими словами, include_special_i
параметр должен быть установлен в True
,
Примеры:
caseless_match('LİMANI', 'limanı', include_special_i=True)
Правда
caseless_match('LİMANI', 'limanı')
Ложь
caseless_match('INTENSIVE', 'intensive', include_special_i=True)
Ложь
caseless_match('INTENSIVE', 'intensive')
Правда