不区分大小写的字符串比较
以不区分大小写的方式比较字符串似乎是微不足道的,但事实并非如此。本节仅考虑 unicode 字符串(Python 3 中的默认值)。请注意,Python 2 可能具有相对于 Python 3 的微妙弱点 - 后者的 unicode 处理要完整得多。
首先要注意的是,在 unicode 中删除大小写的转换并非易事。有 text.lower() !=
text.upper().lower()
的文字,如 ß
:
>>> "ß".lower()
'ß'
>>> "ß".upper().lower()
'ss'
但是,让我们说你想无比地比较 BUSSE
和 Buße
。哎呀,你可能也想比较 BUSSE
和 BUẞE
相等 - 这是更新的资本形式。推荐的方法是使用 casefold
:
Python 3.x >= 3.3
>>> help(str.casefold)
"""
Help on method_descriptor:
casefold(...)
S.casefold() -> str
Return a version of S suitable for caseless comparisons.
"""
不要只使用 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 规范化,但请随时查看文档。然后一个人
>>> unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
True
最后,这里用函数表示:
import unicodedata
def normalize_caseless(text):
return unicodedata.normalize("NFKD", text.casefold())
def caseless_equal(left, right):
return normalize_caseless(left) == normalize_caseless(right)