7

最近在阅读忽略大小写时的 casefold 和字符串比较。我读过 MSDN 标准是使用 InvariantCulture 并且绝对避免使用 toLowercase。但是,从我读过的内容来看,casefold 就像一个更具侵略性的 toLowercase。我的问题是我应该在 Python 中使用 casefold 还是有更多的 Pythonic 标准可以代替?另外,casefold 是否通过了土耳其测试?

4

1 回答 1

17

1) 在 Python 3 中,casefold()应该用于实现无大小写字符串匹配。

从 Python 3.0 开始,字符串存储为 Unicode。Unicode 标准第 3.13 章定义了默认的无大小写匹配,如下所示:

字符串 X 是字符串 Y 的无大小写匹配当且仅当:
toCasefold(X) = toCasefold(Y)

Pythoncasefold()实现了 Unicode 的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)

Pythoncasefold()只能应用默认映射并且无法通过土耳其测试。例如,土耳其语单词“LİMANI”和“limanı”是无大小写的等价词,但"LİMANI".casefold() == "limanı".casefold()返回False. 没有启用替代映射的选项。

3) 如何在 Python 3 中进行无大小写字符串匹配。

Unicode 标准第 3.13 章描述了几种无大小写匹配算法。规范的无casless匹配可能适合大多数用例。该算法已经考虑了所有极端情况。我们只需要添加一个选项即可在非突厥语和突厥语折叠之间切换。

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,则应用 Turkic 映射,如果设置为False默认映射,则使用。

caseless_match()string1对和进行规范的无casless匹配string2。如果字符串是突厥语单词,则include_special_i参数必须设置为True

例子:

>>> caseless_match('LİMANI', 'limanı', include_special_i=True)
True
>>> caseless_match('LİMANI', 'limanı')
False
>>> caseless_match('INTENSIVE', 'intensive', include_special_i=True)
False
>>> caseless_match('INTENSIVE', 'intensive')
True
于 2016-12-24T18:51:03.603 回答