답변:
username = 'MICHAEL89'
if username.upper() in (name.upper() for name in USERNAMES):
...
또는
if username.upper() in map(str.upper, USERNAMES):
...
또는 사용자 정의 방법을 만들 수 있습니다.
[...]
전체 목록을 만듭니다. (name.upper() for name in USERNAMES)
한 번에 생성기와 하나의 필요한 문자열 만 생성합니다.이 작업을 많이 수행하면 메모리를 크게 절약 할 수 있습니다. (매번 확인하기 위해 재사용하는 소문자 사용자 이름 목록을 작성하면 더 많은 비용 절감 효과)
난 당신이 비 침습적 수 있도록 래퍼를 만들 것 입니다. 최소한, 예를 들어 ... :
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:
필요에 따라 동작해야합니다 (오른쪽이 목록, dict 또는 set인지 여부). (문자열 포함에 대해 비슷한 결과를 얻으려면 더 많은 노력이 필요할 수 있습니다 unicode
.
CaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
에 따라 동작"에 해당하지 않는 작동해야합니다.
etc.
하고 "더 많은 노력이 필요합니다"부분);
일반적으로 (적어도 적어도) 원하는 방식으로 동작하도록 객체를 형성합니다. 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)
한 번만 계산 하여 클래스에 저장할 수 있습니다.
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"로 변환합니다.
한 가지 방법이 있습니다.
if string1.lower() in string2.lower():
...
이것이 작동 하려면 string1
및 string2
객체 유형이 모두 이어야합니다 string
.
추가 코드를 작성해야한다고 생각합니다. 예를 들면 다음과 같습니다.
if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
...
이 경우 모든 항목 USERNAMES
을 대문자 로 변환하여 새 목록을 만든 다음이 새 목록과 비교합니다.
최신 정보
으로 @viraptor는 말한다, 대신의 발전기를 사용하는 것이 더 나은 것입니다 map
. @Nathon 의 답변을 참조하십시오 .
itertools
function을 사용할 수 있습니다 imap
. 발전기보다 훨씬 빠르지 만 동일한 목표를 달성합니다.
넌 할 수있어
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에서 온 것입니다. 생성기보다 빠르지 만 호출 될 때 목록의 다음 항목 만 작성합니다.
나는 목록 대신 사전을 위해 이것을 필요로했다 .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:
if 'CaseFudge'.lower() in [x.lower() for x in list]