python - 在Python,不区分大小写的字符串比较?

在Python中进行不区分大小写的字符串比较的最佳方法是什么?

我想以一种非常简单和pythonic的方式将常规字符串的比较封装到字符串存储库中。我也希望有能力使用常规python字符串查找字符串中的值。感谢你的建议。

时间:

 

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 2,在每个字符串或Unicode对象上调用 .lower()

 

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

大多数时候都可以工作,但是,实际上在 @tchrist描述的情况下并不工作。

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

 

>>> utf8_bytes = open(" unicode.txt" , 'r').read()
>>> print repr(utf8_bytes)
'xcexa3xcexafxcfx83xcfx85xcfx86xcexbfxcfx82nxcexa3xcex8axcexa3xcexa5xcexa6xcex9fxcexa3n'
>>> 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中,所有三个form都被解析,并且两个字符串上的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

如果你关心像希腊文这样的三个sigmas的特殊情况,那么使用python 3.

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

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

先转换为小写如何? 你可以使用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__)

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

 

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

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

 

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

这样做之后,你可以让字符串比较方便。

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

 

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

...