我喜欢使用这个表达式
if 'MICHAEL89' in USERNAMES:
...
其中USERNAMES
是一个列表。
有没有办法进行不区分大小写的匹配,或者我需要使用自定义方法?只是想知道是否需要为此编写额外的代码。
我喜欢使用这个表达式
if 'MICHAEL89' in USERNAMES:
...
其中USERNAMES
是一个列表。
有没有办法进行不区分大小写的匹配,或者我需要使用自定义方法?只是想知道是否需要为此编写额外的代码。
username = 'MICHAEL89'
if username.upper() in (name.upper() for name in USERNAMES):
...
或者:
if username.upper() in map(str.upper, USERNAMES):
...
或者,是的,你可以创建一个自定义方法。
str.casefold
推荐用于不区分大小写的字符串匹配。 @nmichaels's solution 可以轻松地进行调整。
使用以下任一方式:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
或者:if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
根据文档:
Casefold(大小写折叠)类似于小写,但更加激进,因为它旨在消除字符串中的所有大小写差异。例如,德语小写字母 'ß' 等同于 "ss"。由于它已经是小写的,
lower()
对 'ß' 不会有任何作用;casefold()
将其转换为 "ss"。
我会创建一个包装器,这样你就不会有侵入性。至少,例如...:
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
的情况下出现警告可能需要更多努力等)。
CaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
,这可能不属于“按要求行事”的范畴。 - Gabeetc.
和“需要更多努力”部分的一部分;-)。 - Alex Martelli通常(至少在面向对象编程中),您会将对象塑造成所需的行为方式。 USERNAMES
中的 name
不区分大小写,因此需要更改:
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)
仅一次并将其存储在类上等等...
这是一种方法:
if string1.lower() in string2.lower():
...
要使此方法起作用,string1
和string2
对象都必须是string
类型。
您可以这样做
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
< p > ifilter
函数来自于 Python 中我最喜欢的模块之一 itertools。它比生成器更快,但只有在调用时才会创建列表的下一个项。
来自此教程的示例:
list1 = ["Apple", "Lenovo", "HP", "Samsung", "ASUS"]
s = "lenovo"
s_lower = s.lower()
res = s_lower in (string.lower() for string in list1)
print(res)
if any(([True if 'MICHAEL89' in username.upper() else False for username in USERNAMES])):
print('username exists in list')
我没有对其进行时间测试。我不确定它有多快/高效。
any
中的单个生成器表达式。您当前在any
调用中使用了一个列表理解和生成器理解。此外,三元运算符True if ... else False
也会对类似于abc_michael89xyz
的用户名产生True
的结果! - ewerybodyif any(name == username.upper() for username in USERNAMES):
- ewerybodyabc_michael89xyz
是正确的,但我认为这正是应该返回 True
的情况,精确匹配并不重要。 - MFAa == b
只能产生 True
或 False
:) - ewerybodyif any(name in username.upper() for username in USERNAMES):
,就完成了! - ewerybodyTrue
被找到时都会立即结束循环!因此,这不仅具有性能优势,而且还具有内存友好性,因为没有额外的列表被即时创建。 - ewerybody我需要将其用于字典而非列表,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:
。
'CaseFudge'.lower() in [x.lower() for x in list]
,则... - fredley[...]
创建整个列表。(name.upper() for name in USERNAMES)
只会创建一个生成器,每次只需要一个字符串 - 如果您经常执行此操作,则可以大量节省内存。(如果您仅创建一次小写用户名的列表并重复使用以进行每次检查,则可以节省更多。) - viraptor