Python:字符串匹配中的lower()与casefold()并转换为小写

17 python string python-2.7 python-3.x

如何进行不区分大小写的字符串比较?

从我从谷歌的理解和上述两个功能的链接:lower()casefold()将转换为小写的字符串,但casefold()甚至会转换为不区分大小写的字母,如ß用德语ss.

关于希腊字母的所有内容,但我的问题一般:

  • 还有其他差异吗?
  • 哪一个更好地转换为小写?
  • 哪一个更好地检查匹配的字符串?

第2部分:

firstString = "der Fluß"
secondString = "der Fluss"

# ß is equivalent to ss
if firstString.casefold() == secondString.casefold():
    print('The strings are equal.')
else:
    print('The strings are not equal.')
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我应该使用:

lower() # the result is not equal which make sense to me

要么:

casefold() # which ß is ss and result is the
        # strings are equal. (since I am a beginner that still does not
        # make sense to me. I see different strings).
Run Code Online (Sandbox Code Playgroud)

dlu*_*kes 29

.lower()和均.casefold()作用于全部 Unicode 代码点

\n

现有的答案存在一些混乱,甚至是已接受的答案(编辑:我指的是当前过时的版本;当前的版本很好)。.lower()和之间的区别.casefold()ASCII 和 Unicode 无关,两者都作用于整个 Unicode 代码点范围,只是方式略有不同。但两者都执行相对复杂的映射,需要在 Unicode 数据库中查找,例如:

\n
>>> "\xc5\xa4".lower()\n\'\xc5\xa5\'\n
Run Code Online (Sandbox Code Playgroud)\n

两者都可以涉及单到多个代码点映射,就像我们在"\xc3\x9f".casefold(). .lower()看看当您应用\ 的对应项时 \xc3\x9f 会发生什么.upper()

\n
>>> "\xc3\x9f".upper()\n\'SS\'\n
Run Code Online (Sandbox Code Playgroud)\n

我发现的一个例子.lower()也是这样做的:

\n
>>> list("\xc4\xb0".lower())\n[\'i\', \'\xcc\x87\']\n
Run Code Online (Sandbox Code Playgroud)\n

因此,诸如“lower()因为没有查找而需要更少的内存或更少的时间,并且它只处理必须转换的 26 个字符”之类的性能声明根本不正确。

\n

绝大多数情况下,这两种操作都会产生相同的结果,但也有少数情况(Unicode 13.0.0 中为 297 种)不会产生相同的结果。您可以这样识别它们:

\n
import sys\nimport unicodedata as ud\n\nprint("Unicode version:", ud.unidata_version, "\\n")\ntotal = 0\nfor codepoint in map(chr, range(sys.maxunicode)):\n    lower, casefold = codepoint.lower(), codepoint.casefold()\n    if lower != casefold:\n        total += 1\n        for conversion, converted in zip(\n            ("orig", "lower", "casefold"),\n            (codepoint, lower, casefold)\n        ):\n            print(conversion, [ud.name(cp) for cp in converted], converted)\n        print()\nprint("Total differences:", total)\n
Run Code Online (Sandbox Code Playgroud)\n

何时使用哪个

\n

Unicode 标准在第 3.13 节中将小写作为默认大小写转换的一部分,并且在下面描述了默认大小写折叠。第一段说:

\n
\n

大小写折叠与大小写转换有关。然而,大小写折叠的主要目的是有助于字符串的无大小写匹配,而大小写转换的主要目的是将字符串放入特定的大小写形式。

\n
\n

我的经验法则基于此:

\n
    \n
  • 想要向用户显示字符串的小写版本?使用.lower()
  • \n
  • 想要进行不区分大小写的字符串比较吗?使用.casefold()
  • \n
\n

(作为旁注,我经常打破这个经验法则并.lower()全面使用,只是因为它的打字时间更短,输出绝大多数是相同的,并且其中的差异不会影响我通常使用的语言跨越并一起工作。但不要像我一样;))

\n

需要强调的是,就复杂性而言,这两种操作基本上是相同的,只是使用略有不同的映射——这是 Unicode 对小写字母的抽象定义:

\n
\n

R2 toLowercase(X):将X中的每个字符C映射到Lowercase_Mapping(C)。

\n
\n

这是它对大小写折叠的抽象定义:

\n
\n

R4 toCasefold(X):将X中的每个字符C映射到Case_Folding(C)。

\n
\n

在Python的官方文档中

\n

Python 文档非常清楚这就是各个方法的作用,它们甚至向用户指出了前面提到的第 3.13 节。

\n

他们描述.lower()为将大小写字符转换为小写,其中大小写字符是“一般类别属性为 \xe2\x80\x9cLu\xe2\x80\x9d (字母,大写)、\xe2\x80\x9cLl\xe2\x80 之一的字符\x9d (字母,小写),或 \xe2\x80\x9cLt\xe2\x80\x9d (字母,标题大写)"。与 和 大写相同.upper()

\n

对于.casefold(),文档明确指出它用于“无大小写匹配”,并且它“类似于小写,但更激进,因为它旨在删除字符串中的所有大小写区别”。

\n


Dav*_*eth 23

Casefolding是一个更积极的lower()版本,它被设置为使许多更独特的unicode角色更具可比性.这是规范化文本的另一种形式,最初可能看起来非常不同,但它考虑了许多不同语言的字符.

我建议你仔细看看折叠实际上是什么情况,所以这是一个好的开始:W3 Case Folding Wiki

要回答你的另外两个问题,如果你严格使用英语,则lower()和casefold()应该产生完全相同的结果.但是,如果您尝试规范化使用超过我们简单的26个字母字母的其他语言的文本,我会使用casefold()来比较您的字符串,因为它将产生更一致的结果.

另一个来源: Elastic.co Case Folding

编辑:我刚刚在SO上找到了另一个非常好的相关答案来解决一个稍微不同的问题(做一个不区分大小写的字符串比较)

  • 吹毛求疵:认为英语文本仅包含 ASCII 字符是幼稚的,尽管现在这种情况可能相当罕见。所有这些来自法语和其他语言的借词。 (4认同)
  • `.lower()` 与 `.casefold()` 与 ASCII 与 Unicode 无关,请参阅[我的答案](/sf/answers/5229148501/) 了解详细信息。 (3认同)
  • @Dave 我的观点是英语没有“简单的 26 个字母的字母表”。Naïve with ï 是有效的英语拼写(如果很少见)。有些人仍然使用diaeres等。(来自 oldnewthing 或纽约客的 Raymond Chen 浮现在脑海中) (2认同)
  • @dlukes 是完全正确的。去看他的回答吧 (2认同)