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

时间:2008-11-26 01:06:45

标签: python comparison case-insensitive

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

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

13 个答案:

答案 0 :(得分:496)

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

答案 1 :(得分:409)

以不区分大小写的方式比较字符串看起来像是微不足道的东西,但事实并非如此。我将使用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)

答案 2 :(得分:57)

使用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显示在上面的解释器打印输出中。)

答案 3 :(得分:27)

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

Python 3中的

X.casefold() == Y.casefold()实现了“默认的无壳匹配”(D144)。

Casefolding不会保留所有实例中字符串的规范化,因此需要进行规范化('å''å')。 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

对于'㎒'(U + 3392)和“标识符无标记匹配”等情况,还有兼容性无标记匹配(D146),以简化和优化caseless matching of identifiers

答案 4 :(得分:7)

我使用here看到了此解决方案regex

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

答案 5 :(得分:5)

您可以使用 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.

答案 6 :(得分:3)

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

答案 7 :(得分:2)

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

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

答案 8 :(得分:0)

这是另一个正则表达式,我在上周学会了爱/恨,因此通常导入(在这种情况下为)反映我感觉的东西! 做一个正常的函数....要求输入,然后使用.... something = re.compile(r'foo * | spam *',是的.I)...... re.I(是的.I下面)与IGNORECASE相同,但是您编写它时不能犯太多错误!

然后,您使用正则表达式搜索消息,但老实说应该只有几页,但要点是foo或垃圾邮件通过管道传递在一起,并且忽略大小写。 然后,如果找到任何一个,则lost_n_found将显示其中之一。如果两者都不是,则lost_n_found等于无。如果不等于null,请使用“ 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")

答案 9 :(得分:0)

您可以在 str.contains() 中提及 case=False

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

答案 10 :(得分:-1)

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__)

答案 11 :(得分:-8)

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

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

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

答案 12 :(得分:-8)

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

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

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