programing

대소문자를 구분하지 않는 '입력'

itsource 2022. 9. 24. 23:44
반응형

대소문자를 구분하지 않는 '입력'

나는 이 표현을 쓰는 것을 좋아한다.

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의 용액은 트라이얼하게 적응할 수 있다.

다음 중 하나를 사용합니다.

if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):

또는 다음 중 하나를 선택합니다.

if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):

문서에 따르면:

케이스 폴딩은 소문자와 비슷하지만 문자열 내의 대소문자를 모두 제거하는 것을 목적으로 하기 때문에 더 적극적입니다.예를 들어 독일어 소문자 '''는 '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등)

보통(적어도) 원하는 방식으로 동작하도록 객체를 형성합니다. 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)한 번만 수업에 저장해 두는 등...

한 가지 방법이 있습니다.

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기능은 Python에서 내가 가장 좋아하는 모듈 중 하나인 itertools에서 가져온 것입니다.생성기보다 빠르지만 호출 시 목록의 다음 항목만 생성합니다.

한 줄에 정리하자면, 저는 이렇게 했습니다.

if any(([True if 'MICHAEL89' in username.upper() else False for username in USERNAMES])):
    print('username exists in list')

하지만 시간적으로 테스트하진 않았어요.나는 그것이 얼마나 빠르고 효율적인지 잘 모르겠다.

5센트 (잘못)

""의 "a"는 "join(["A")".lower()의 "a"입니다.

갱신하다

아, @jpp, 완전히 동의해, 나쁜 관행의 예를 들겠습니다.

사전에는 목록 대신 이것이 필요했는데, 요헨 솔루션이 그 경우에 가장 우아했기 때문에 조금 수정했습니다.

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:

튜토리얼의 예:

list1 = ["Apple", "Lenovo", "HP", "Samsung", "ASUS"]

s = "lenovo"
s_lower = s.lower()

res = s_lower in (string.lower() for string in list1)

print(res)

언급URL : https://stackoverflow.com/questions/3627784/case-insensitive-in

반응형