如何在Python中以不区分大小写的方式比较字符串?

我想使用简单的python代码将常规字符串的比较封装到存储库字符串中。我也想有能力在字典中查找值哈希字符串使用常规的python字符串。


当前回答

Unicode标准的第3.13节定义了无大小写的算法 匹配。

X.casefold() == Python 3中的Y.casefold()实现了“默认的无大小写匹配”(D144)。

案例折叠不会在所有实例中保存字符串的规范化,因此需要进行规范化('å' vs。“一个”)。D145引入了“规范无大小写匹配”:

import unicodedata

def NFD(text):
    return unicodedata.normalize('NFD', text)

def canonical_caseless(text):
    return NFD(NFD(text).casefold())

对于涉及U+0345字符的非常罕见的边缘情况,NFD()被调用两次。

例子:

>>> 'å'.casefold() == 'å'.casefold()
False
>>> canonical_caseless('å') == canonical_caseless('å')
True

此外,还有兼容无案例匹配(D146),如“mhz”(U+3392)和“标识符无案例匹配”,以简化和优化标识符的无案例匹配。

其他回答

Unicode标准的第3.13节定义了无大小写的算法 匹配。

X.casefold() == Python 3中的Y.casefold()实现了“默认的无大小写匹配”(D144)。

案例折叠不会在所有实例中保存字符串的规范化,因此需要进行规范化('å' vs。“一个”)。D145引入了“规范无大小写匹配”:

import unicodedata

def NFD(text):
    return unicodedata.normalize('NFD', text)

def canonical_caseless(text):
    return NFD(NFD(text).casefold())

对于涉及U+0345字符的非常罕见的边缘情况,NFD()被调用两次。

例子:

>>> 'å'.casefold() == 'å'.casefold()
False
>>> canonical_caseless('å') == canonical_caseless('å')
True

此外,还有兼容无案例匹配(D146),如“mhz”(U+3392)和“标识符无案例匹配”,以简化和优化标识符的无案例匹配。

考虑使用jaraco.text中的FoldedCase:

>>> from jaraco.text import FoldedCase
>>> FoldedCase('Hello World') in ['hello world']
True

如果你想要一个不考虑大小写的字典,使用来自jaraco.collections的FoldedCaseKeyedDict:

>>> from jaraco.collections import FoldedCaseKeyedDict
>>> d = FoldedCaseKeyedDict()
>>> d['heLlo'] = 'world'
>>> list(d.keys()) == ['heLlo']
True
>>> d['hello'] == 'world'
True
>>> 'hello' in d
True
>>> 'HELLO' in d
True
from re import search, IGNORECASE

def is_string_match(word1, word2):
    #  Case insensitively function that checks if two words are the same
    # word1: string
    # word2: string | list

    # if the word1 is in a list of words
    if isinstance(word2, list):
        for word in word2:
            if search(rf'\b{word1}\b', word, IGNORECASE):
                return True
        return False

    # if the word1 is same as word2
    if search(rf'\b{word1}\b', word2, IGNORECASE):
        return True
    return False

is_match_word = is_string_match("Hello", "hELLO") 
True

is_match_word = is_string_match("Hello", ["Bye", "hELLO", "@vagavela"])
True

is_match_word = is_string_match("Hello", "Bye")
False

我看到这个用正则表达式的解。

import re
if re.search('mandy', 'Mandy Pande', re.IGNORECASE):
# is True

它和口音很搭

In [42]: if re.search("ê","ê", re.IGNORECASE):
....:        print(1)
....:
1

但是,它不适用于unicode字符不区分大小写的情况。谢谢@Rhymoid指出,我的理解是,它需要确切的符号,因为情况是真实的。回显如下:

In [36]: "ß".lower()
Out[36]: 'ß'
In [37]: "ß".upper()
Out[37]: 'SS'
In [38]: "ß".upper().lower()
Out[38]: 'ss'
In [39]: if re.search("ß","ßß", re.IGNORECASE):
....:        print(1)
....:
1
In [40]: if re.search("SS","ßß", re.IGNORECASE):
....:        print(1)
....:
In [41]: if re.search("ß","SS", re.IGNORECASE):
....:        print(1)
....:

我找到了一个干净的解决方案,我正在使用一些固定的文件扩展名。

from pathlib import Path


class CaseInsitiveString(str):
   def __eq__(self, __o: str) -> bool:
      return self.casefold() == __o.casefold()

GZ = CaseInsitiveString(".gz")
ZIP = CaseInsitiveString(".zip")
TAR = CaseInsitiveString(".tar")

path = Path("/tmp/ALL_CAPS.TAR.GZ")

GZ in path.suffixes, ZIP in path.suffixes, TAR in path.suffixes, TAR == ".tAr"

# (True, False, True, True)