首页 文章

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

提问于
浏览
416

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

我想以一种非常简单和Pythonic的方式将常规字符串的比较封装到存储库字符串中 . 我还希望能够使用常规python字符串在字符串中查找值 .

11 回答

  • 5

    假设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)"
    
  • 0

    以不区分大小写的方式比较字符串似乎是微不足道的,但事实并非如此 . 我将使用Python 3,因为Python 2在这里不发达 .

    首先要注意的是,在unicode中删除大小写的转换并非易事 . 有 text.lower() != text.upper().lower() 的文本,例如 "ß"

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

    但是,让我们说你想无谓地比较 "BUSSE""Buße" . 哎呀,你可能也想比较 "BUSSE""BUẞE" 相等 - 这是更新的资本形式 . 推荐的方法是使用 casefold

    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)
    
  • 452

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

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

    ......大部分时间都会工作,但确实不适用于situations @tchrist has described .

    假设我们有一个名为 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
    

    因此,如果您关注像希腊语中的三个sigma这样的边缘情况,请使用Python 3 .

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

  • 372

    Section 3.13 of the Unicode standard定义了无壳匹配的算法 .

    Python 3中的 X.casefold() == Y.casefold() 实现了"default caseless matching"(D144) .

    Casefolding不会在所有实例中保留字符串的规范化,因此需要进行规范化( 'å''å' ) . D145介绍"canonical caseless matching":

    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
    

    对于诸如 '㎒' (U 3392)和"identifier caseless matching"之类的情况,还有兼容性无情况匹配(D146),以简化和优化caseless matching of identifiers .

  • -9

    我使用regex看到了这个解决方案here .

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

    如何先转换为小写?你可以使用 string.lower() .

  • 0

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

    >>> "hello".upper() == "HELLO".upper()
    True
    >>>
    
  • 18
    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__)
    
  • 2

    这是我在上周学会爱/恨的另一个正则表达式,因此通常导入(在这种情况下是肯定的)反映我的感觉的东西!做一个正常的功能....请求输入,然后使用.... something = re.compile(r'foo * | spam *',yes.I)...... re.I(yes.I下面)与IGNORECASE相同,但你不能写出多少错误!

    然后,您使用正则表达式搜索您的邮件,但老实说,它应该是自己的几页,但关键是foo或垃圾邮件一起管道并且大小写被忽略 . 然后如果找到任何一个,那么lost_n_found将显示其中一个 . 如果两者都没有,则lost_n_found等于None . 如果它不等于none,则使用“return lost_n_found.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")
    
  • 54

    如果您有包含字符串的列表,并且您希望将不同列表中的字符串与不区分大小写进行比较 . 这是我的解决方案 .

    list1 = map(lambda each:each.lower(), list1)
    list2 = map(lambda each:each.lower(), list2)
    

    这样做之后,你可以轻松地进行字符串比较 .

  • 3

    我已经用它来完成比较两个字符串更有用的东西:

    def strings_iequal(first, second):
        try:
            return first.upper() == second.upper()
        except AttributeError:
            if not first:
                if not second:
                    return True
    

    更新:如gerrit所述,这个答案有一些错误 . 这是多年前的事了,我不再记得我用它了 . 我记得写过测试,但他们现在有什么好处!

相关问题