不区分大小写的“in”
- 2025-02-12 10:03:00
- admin 原创
- 45
问题描述:
我喜欢用这个表达方式
if 'MICHAEL89' in USERNAMES:
...
其中USERNAMES
是一个列表。
有没有办法匹配不区分大小写的项,还是我需要使用自定义方法?只是想知道是否需要为此编写额外的代码。
解决方案 1:
username = 'MICHAEL89'
if username.upper() in (name.upper() for name in USERNAMES):
...
或者:
if username.upper() in map(str.upper, USERNAMES):
...
或者,是的,您可以创建自定义方法。
解决方案 2:
str.casefold
建议用于不区分大小写的字符串匹配。@nmichaels 的解决方案可以轻松适应。
使用以下任一方法:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
或者:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
根据文档:
大小写折叠类似于小写,但更激进,因为它旨在消除字符串中的所有大小写区别。例如,德语小写字母“ß”相当于“ss”。由于它已经是小写,因此
lower()
不会对“ß”执行任何操作;casefold()
将其转换为“ss”。
解决方案 3:
我会制作一个包装器,这样你就可以不受到侵入。最低限度,例如...:
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
等)。
解决方案 4:
通常(至少在 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)
仅计算一次并将其存储在类中,等等...
解决方案 5:
以下是一种方法:
if string1.lower() in string2.lower():
...
为了使其正常工作,string1
和string2
对象都必须是类型string
。
解决方案 6:
我认为你必须编写一些额外的代码。例如:
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
在这种情况下,我们将形成一个新列表,将所有条目USERNAMES
转换为大写,然后与这个新列表进行比较。
更新
正如@viraptor所说,使用生成器代替 甚至更好map
。请参阅@Nathon的回答。
解决方案 7:
你可以做
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 模块之一。它比生成器更快,但仅在调用时创建列表中的下一个项目。
解决方案 8:
我的五点错误看法
“”中的“a”.join(['A']).lower()
更新
哎哟,完全同意@jpp,我会将其作为不良做法的例子:(
解决方案 9:
为了将其放在一行中,我做了以下事情:
if any(([True if 'MICHAEL89' in username.upper() else False for username in USERNAMES])):
print('username exists in list')
不过,我还没有进行时间方面的测试。我不确定它有多快/高效。
解决方案 10:
本教程中的示例:
list1 = ["Apple", "Lenovo", "HP", "Samsung", "ASUS"]
s = "lenovo"
s_lower = s.lower()
res = s_lower in (string.lower() for string in list1)
print(res)
解决方案 11:
我需要这个字典而不是列表,Jochen 解决方案对于这种情况是最优雅的,所以我对它进行了一些修改:
class CaseInsensitiveDict(dict):
''' requests special dicts are case insensitive when using the in operator,
this implements a similar behaviour'''
def __contains__(self, name): # implements `in`
return name.casefold() in (n.casefold() for n in self.keys())
现在您可以像这样转换字典USERNAMESDICT = CaseInsensitiveDict(USERNAMESDICT)
并使用if 'MICHAEL89' in USERNAMESDICT:
解决方案 12:
我正在使用 Pyhton 3.10.5
假设我有一个列表
USERNAMES = ['joy23', 'michael89', 'rony224', 'samrat445']
现在,如果我想检查“michael89”是否在列表中而不考虑大小写,则以下代码有效:
'michael89'.casefold() in USERNAMES
输出将为真。
同样,如果我想检查“MICHAEL89”是否在列表中而不考虑大小写,代码是:
'MICHAEL89'.casefold() in USERNAMES
输出也将为真。
'miCHAel89'.casefold() in USERNAMES
这再次返回 true。
因此,这里的主要问题是 USERNAMES 列表应仅包含小写字母。如果您将 USERNAMES 的所有项目都保存为小写字母。您可以使用以下方法轻松解决问题:
if 'MICHAEL89'.casefold() in USERNAMES:
......