不区分大小写'in' - Python

问题描述 投票:127回答:8

我喜欢用这个表达方式

if 'MICHAEL89' in USERNAMES:
    ...

其中USERNAMES是一个清单


有没有办法匹配不区分大小写的项目或我需要使用自定义方法?只是想知道是否需要为此编写额外的代码。

谢谢大家!

python list case-insensitive
8个回答
154
投票
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
    ...

或者:

if 'MICHAEL89' in map(str.upper, USERNAMES):
    ...

或者,是的,您可以制作自定义方法。


18
投票

我会做一个包装,所以你可以是非侵入性的。最低限度,例如...:

class CaseInsensitively(object):
    def __init__(self, s):
        self.__s = s.lower()
    def __hash__(self):
        return hash(self.__s)
    def __eq__(self, other):
        # ensure proper comparison between instances of this class
        try:
           other = other.__s
        except (TypeError, AttributeError):
          try:
             other = other.lower()
          except:
             pass
        return self.__s == other

现在,if CaseInsensitively('MICHAEL89') in whatever:应该按照要求行事(无论右侧是列表,字典还是集合)。 (可能需要更多的努力来实现字符串包含的类似结果,在某些涉及unicode的情况下避免警告等)。


10
投票

通常(至少在oop中)你塑造你的对象以按照你想要的方式行事。 name in USERNAMES不区分大小写,所以USERNAMES需要改变:

class NameList(object):
    def __init__(self, names):
        self.names = names

    def __contains__(self, name): # implements `in`
        return name.lower() in (n.lower() for n in self.names)

    def add(self, name):
        self.names.append(name)

# now this works
usernames = NameList(USERNAMES)
print someone in usernames

关于这一点的好处在于它为许多改进打开了路径,而无需更改类外的任何代码。例如,你可以将self.names更改为一组以便更快地查找,或者只计算一次(n.lower() for n in self.names)并将其存储在类中,依此类推......


6
投票

我想你必须写一些额外的代码。例如:

if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
   ...

在这种情况下,我们正在形成一个新列表,其中USERNAMES中的所有条目都转换为大写,然后与此新列表进行比较。

更新

正如@viraptor所说,使用发电机代替map更好。见@Nathonanswer


6
投票

这是一种方式:

if string1.lower() in string2.lower(): 
    ...

为此,string1string2对象必须是string类型。


4
投票

你可以做到

matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES) 

更新:玩了一下,我想你可以使用更好的短路类型方法

matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
    #your code here

ifilter函数来自itertools,这是我在Python中最喜欢的模块之一。它比生成器更快,但只在调用时才创建列表的下一个项目。


4
投票

str.casefold建议用于不区分大小写的字符串匹配。 @nmichaels's solution可以简单地适应。

使用:

if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):

要么:

if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):

根据docs

Casefolding类似于lowercasing但更具攻击性,因为它旨在删除字符串中的所有大小写区别。例如,德语小写字母'ß'相当于“ss”。由于它已经是小写的,lower()对'ß'没有任何作用; casefold()将其转换为“ss”。


0
投票

我的5(错)美分

“a”in“”。join(['A'])。lower()

UPDATE

哎哟,完全同意@jpp,我会继续作为不良做法的一个例子:(

© www.soinside.com 2019 - 2024. All rights reserved.