不区分大小写'in' - Python

Rad*_*Hex 136 python string list case-insensitive

我喜欢用这个表达方式

if 'MICHAEL89' in USERNAMES:
    ...
Run Code Online (Sandbox Code Playgroud)

USERNAMES列表在哪里


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

谢谢大家!

nmi*_*els 161

if 'MICHAEL89' in (name.upper() for name in USERNAMES):
    ...
Run Code Online (Sandbox Code Playgroud)

或者:

if 'MICHAEL89' in map(str.upper, USERNAMES):
    ...
Run Code Online (Sandbox Code Playgroud)

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

  • `[...]`创建整个列表.`(USERNAMES中名称的name.upper())`一次只创建一个生成器和一个需要的字符串 - 如果你经常做这个操作,可以节省大量内存.(如果您只是创建一个每次重复检查的小写用户名列表,可以节省更多费用) (41认同)
  • `if'CaseFudge'.lower()in [x.lower()for x in list]` (8认同)
  • 出于性能原因,在构建字典时更喜欢降低所有键. (2认同)

Ale*_*lli 19

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

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
Run Code Online (Sandbox Code Playgroud)

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

  • 如果在''Michael89':True}中CaseInsensitively('MICHAEL89'),那对dict不起作用的尝试:print"found" (3认同)
  • Xavier:在{CaseInsensitively('Michael89')中你需要`CaseInsensitively('MICHAEL89'):真的}`为了工作,这可能不属于"按要求行事". (2认同)
  • @Nathon,在我看来,不得不侵入性地更改容器是“感到沉重”的操作。一个完全非侵入性的包装器:比这个包装器轻多少?不多;-)。@Xavier是带有大小写混合的键/项的字典或集合的RHS,需要它们自己的非侵入性包装器(简短的“ etc.”的一部分,我的答案中“需要更多的精力”部分;-)。 (2认同)

Joc*_*zel 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
Run Code Online (Sandbox Code Playgroud)

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


Man*_*dan 6

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

if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
   ...
Run Code Online (Sandbox Code Playgroud)

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

更新

正如@viraptor所说,使用发电机代替它更好map.看@Nathon回答.


Use*_*ser 6

这是一种方法:

if string1.lower() in string2.lower(): 
    ...
Run Code Online (Sandbox Code Playgroud)

为此,string1string2对象都必须是type string

  • AttributeError:“列表”对象没有属性“较低” (5认同)

jpp*_*jpp 6

str.casefold建议使用不区分大小写的字符串匹配。@nmichaels的解决方案可以轻松调整。

使用以下任一方法:

if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Run Code Online (Sandbox Code Playgroud)

要么:

if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
Run Code Online (Sandbox Code Playgroud)

根据文档

大小写折叠类似于小写字母,但更具侵略性,因为它旨在消除字符串中的所有大小写区别。例如,德语小写字母“ß”等效于“ ss”。由于它已经是小写字母,lower()因此对“ß”无效。casefold() 将其转换为“ ss”。


whe*_*ies 5

你可以做

matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES) 
Run Code Online (Sandbox Code Playgroud)

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

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

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