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

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


假设ASCII字符串:

string1 = 'Hello'
string2 = 'hello'

if string1.lower() == string2.lower():
    print("The strings are the same (case insensitive)")
else:
    print("The strings are NOT the same (case insensitive)")

从Python 3.3开始,casefold()是一个更好的选择:

string1 = 'Hello'
string2 = 'hello'

if string1.casefold() == string2.casefold():
    print("The strings are the same (case insensitive)")
else:
    print("The strings are NOT the same (case insensitive)")

如果您想要一个处理更复杂unicode比较的更全面的解决方案,请参阅其他答案。


通常的方法是将字符串大写或小写,以便进行查找和比较。例如:

>>> "hello".upper() == "HELLO".upper()
True
>>> 

先转换成小写字母怎么样?你可以使用string.lower()。


def insenStringCompare(s1, s2):
    """ Method that takes two strings and returns True or False, based
        on if they are equal, regardless of case."""
    try:
        return s1.lower() == s2.lower()
    except AttributeError:
        print "Please only pass strings into this method."
        print "You passed a %s and %s" % (s1.__class__, s2.__class__)

使用Python 2,在每个字符串或Unicode对象上调用.lower()…

string1.lower() == string2.lower()

...大部分时间都有效,但在@tchrist所描述的情况下确实不起作用。

假设我们有一个名为unicode.txt的文件,其中包含两个字符串Σίσυφος和ΣΊΣΥΦΟΣ。使用Python 2:

>>> utf8_bytes = open("unicode.txt", 'r').read()
>>> print repr(utf8_bytes)
'\xce\xa3\xce\xaf\xcf\x83\xcf\x85\xcf\x86\xce\xbf\xcf\x82\n\xce\xa3\xce\x8a\xce\xa3\xce\xa5\xce\xa6\xce\x9f\xce\xa3\n'
>>> u = utf8_bytes.decode('utf8')
>>> print u
Σίσυφος
ΣΊΣΥΦΟΣ

>>> first, second = u.splitlines()
>>> print first.lower()
σίσυφος
>>> print second.lower()
σίσυφοσ
>>> first.lower() == second.lower()
False
>>> first.upper() == second.upper()
True

Σ字符有两种小写形式ς和Σ, .lower()不能区分大小写进行比较。

然而,从Python 3开始,这三种表单都将解析为ς,并且在两个字符串上调用lower()将正确工作:

>>> s = open('unicode.txt', encoding='utf8').read()
>>> print(s)
Σίσυφος
ΣΊΣΥΦΟΣ

>>> first, second = s.splitlines()
>>> print(first.lower())
σίσυφος
>>> print(second.lower())
σίσυφος
>>> first.lower() == second.lower()
True
>>> first.upper() == second.upper()
True

所以如果你关心边界情况,比如希腊语中的3 sigma,请使用python3。

(作为参考,Python 2.7.3和Python 3.3.0b1显示在上面的解释器打印输出中。)


以不区分大小写的方式比较字符串似乎无关紧要,但事实并非如此。我将使用Python 3,因为Python 2在这里还不发达。

首先要注意的是,Unicode中的大小写删除转换并不简单。存在text.lower() != text.upper().lower()的文本,例如"ß":

>>> "ß".lower()
'ß'
>>> "ß".upper().lower()
'ss'

但是让我们假设你想无案例地比较“BUSSE”和“Buße”。见鬼,您可能还想比较“BUSSE”和“BUẞE”相等——这是较新的大写形式。推荐使用casefold:

str.casefold () 返回字符串的大小写折叠副本。折叠的字符串可用于 caseless匹配。 大小写折叠类似于小写,但更激进,因为它是 用于删除字符串中的所有大小写区别。[…]

不要只使用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)

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

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)
....:

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)和“标识符无案例匹配”,以简化和优化标识符的无案例匹配。


这是另一个正则表达式,我已经学会了爱/恨在过去的一周,所以通常导入(在这种情况下是),反映了我的感受! 做一个正常的函数....征求意见,然后使用....东西= re.compile垃圾邮件(r 'foo * | *’,是的)……re.I(是的。我下面)是相同的IGNORECASE,但你不能犯很多错误写它!

然后你使用正则表达式搜索你的消息,但老实说,这应该是在自己的几页,但重点是,foo或垃圾邮件管道在一起,大小写被忽略。 然后,如果找到其中任何一个,lost_n_found将显示其中一个。如果都不是,则lost_n_found等于None。如果它不等于none,则使用return lost_n_find .lower()返回小写的user_input

这让你更容易匹配任何区分大小写的东西。最后(NCS)代表“没有人认真关心……!”或不区分大小写....无论哪种

如果有人有任何问题,请问我。

    import re as yes

    def bar_or_spam():

        message = raw_input("\nEnter FoO for BaR or SpaM for EgGs (NCS): ") 

        message_in_coconut = yes.compile(r'foo*|spam*',  yes.I)

        lost_n_found = message_in_coconut.search(message).group()

        if lost_n_found != None:
            return lost_n_found.lower()
        else:
            print ("Make tea not love")
            return

    whatz_for_breakfast = bar_or_spam()

    if whatz_for_breakfast == foo:
        print ("BaR")

    elif whatz_for_breakfast == spam:
        print ("EgGs")

你可以在str.contains()中提到case=False

data['Column_name'].str.contains('abcd', case=False)

您可以使用casefold()方法。casefold()方法在比较时忽略案例。

firstString = "Hi EVERYONE"
secondString = "Hi everyone"

if firstString.casefold() == secondString.casefold():
    print('The strings are equal.')
else:
    print('The strings are not equal.')

输出:

The strings are equal.

def search_specificword(key, stng):
    key = key.lower()
    stng = stng.lower()
    flag_present = False
    if stng.startswith(key+" "):
        flag_present = True
    symb = [',','.']
    for i in symb:
        if stng.find(" "+key+i) != -1:
            flag_present = True
    if key == stng:
        flag_present = True
    if stng.endswith(" "+key):
        flag_present = True
    if stng.find(" "+key+" ") != -1:
        flag_present = True
    print(flag_present)
    return flag_present

输出: search_specificword(“经济适用房”,“欧洲经济适用房的核心”) 假

search_specificword(“经济适用房”,“经济适用房的核心,在欧洲”) 真正的


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

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)

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

考虑使用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