[python] 대소 문자를 구분하지 않는 ‘입력’
나는 표현을 좋아한다
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):
...
또는 사용자 정의 방법을 만들 수 있습니다.
답변
난 당신이 비 침습적 수 있도록 래퍼를 만들 것 입니다. 최소한, 예를 들어 … :
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
.
답변
일반적으로 (적어도 적어도) 원하는 방식으로 동작하도록 객체를 형성합니다. 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 의 답변을 참조하십시오 .
답변
넌 할 수있어
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에서 온 것입니다. 생성기보다 빠르지 만 호출 될 때 목록의 다음 항목 만 작성합니다.