不區分大小寫的字串比較
以不區分大小寫的方式比較字串似乎是微不足道的,但事實並非如此。本節僅考慮 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)