ti-enxame.com

Caso insensível 'in' - Python

Eu amo usar a expressão

if 'MICHAEL89' in USERNAMES:
    ...

onde USERNAMES é uma lista


Existe alguma maneira de combinar itens com insensibilidade a maiúsculas ou preciso usar um método personalizado? Basta saber se há necessidade de escrever código extra para isso.

Obrigado a todos!

129
RadiantHex
if 'MICHAEL89' in (name.upper() for name in USERNAMES):
    ...

Alternativamente:

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

Ou, sim, você pode criar um método personalizado.

152
nmichaels

Eu faria um wrapper para que você não seja invasivo. Minimamente, por exemplo ...:

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

Agora, if CaseInsensitively('MICHAEL89') in whatever: deve se comportar conforme necessário (se o lado direito é uma lista, um comando ou um conjunto). (Pode ser necessário mais esforço para obter resultados semelhantes para inclusão de cadeia de caracteres, evitar avisos em alguns casos envolvendo unicode, etc).

17
Alex Martelli

Normalmente (no oop, pelo menos) você molda seu objeto para se comportar da maneira que você quer. name in USERNAMES não faz distinção entre maiúsculas e minúsculas, portanto USERNAMES precisa mudar:

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

A grande coisa sobre isso é que ele abre o caminho para muitas melhorias, sem ter que alterar qualquer código fora da classe. Por exemplo, você poderia alterar o self.names para um conjunto para pesquisas mais rápidas, ou calcular o (n.lower() for n in self.names) apenas uma vez e armazená-lo na classe e assim por diante ...

10
Jochen Ritzel

Eu acho que você tem que escrever algum código extra. Por exemplo:

if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES):
   ...

Nesse caso, estamos formando uma nova lista com todas as entradas em USERNAMES convertidas em maiúsculas e, em seguida, comparando com essa nova lista.

Atualizar

Como @ viraptor diz, é melhor usar um gerador ao invés de map. Veja @ Nathon 's resposta .

6
Manoj Govindan

Aqui está um jeito:

if string1.lower() in string2.lower(): 
    ...

Para que isso funcione, os objetos string1 e string2 devem ser do tipo string.

6
User

Você poderia fazer

matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES) 

Atualização: brincou um pouco e estou pensando que você poderia ter uma melhor abordagem de tipo de curto-circuito usando

matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
    #your code here

A função ifilter é do itertools, um dos meus módulos favoritos dentro do Python. É mais rápido que um gerador, mas apenas cria o próximo item da lista quando é chamado.

4
wheaties

str.casefold é recomendado para correspondência de cadeia sem distinção entre maiúsculas e minúsculas. @ solução do nmichaels pode ser adaptada trivialmente.

Use:

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

Ou:

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

Conforme o docs :

Casefolding é semelhante a minúsculas, mas mais agressivo, porque se destina a remover todas as distinções de maiúsculas e minúsculas em uma seqüência de caracteres. Por exemplo, a letra minúscula alemã 'ß' é equivalente a "ss". Como já é minúscula, lower() não faria nada para 'ß'; casefold() converte para "ss".

4
jpp

Meus 5 (errados) centavos

'a' em "" .join (['A']). lower ()

ATUALIZAR

Ai, concordo totalmente @jpp, vou manter como exemplo de má prática :(

0
GBrian