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

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

我想使用简单的Pythonic代码将常规字符串与存储库字符串的比较进行封装。我还希望能够使用常规python字符串在字符串散列的字典中查找值。

1056487 次浏览

假设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开始,所有三个表单都将解析为π,并且在两个字符串上都可以正常工作:

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

因此,如果您关心像希腊语中的三个西格玛这样的边缘情况,请使用Python 3。

(作为参考,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()

返回字符串的大小写副本。大小写字符串可用于 无框匹配。

打字法类似于小写,但更具侵略性,因为它是 用于删除字符串中的所有大小写区别。[…]

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

我看到这个解决方案这里使用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)
....:

Unicode标准第3.13节定义了无案例算法 匹配。

Python 3中的X.casefold() == 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

还有用于'㎒'(U+3392)和“标识符无案例匹配”等案例的兼容性无案例匹配(D146),以简化和优化标识符的无大小写匹配

这是另一个正则表达式,我在上周学会了爱/恨,所以通常导入(在这种情况下是的)反映我感觉的东西! 做一个普通的函数……请求输入,然后使用……东西=re.compile(r'foo*|spam*', yes. I)……re. I(yes. I在下面)和IGNORECASE一样,但是你不能犯那么多错误!

然后您使用regex搜索您的消息,但老实说,这应该是它自己的几页,但重点是foo或垃圾邮件是管道连接在一起的,大小写被忽略。 然后如果找到任何一个,那么lost_n_found将显示它们中的一个。如果两者都不lost_n_found等于无。如果它不等于无,则使用“返回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")

您可以在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中的折叠表单

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

如果你想要一个不受大小写影响的文本字典,请使用jaraco.collections中的文件夹

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