Expressões regulares: pesquisa na lista

87

Quero filtrar strings em uma lista com base em uma expressão regular.

Existe algo melhor do que [x for x in list if r.match(x)]?

leoluk
fonte

Respostas:

114

Você pode criar um iterador no Python 3.x ou uma lista no Python 2.x usando:

filter(r.match, list)

Para converter o iterador Python 3.x em uma lista, basta lançá-lo; list(filter(..)).

sepp2k
fonte
2
Na verdade, as compreensões de lista são geralmente preferidas a construções funcionais, como filtro, redução, lambda, etc.
Ivo van der Wijk,
37
@Ivo: Geralmente são preferidos porque costumam ser mais claros e, muitas vezes, mais sucintos. Porém, neste caso, a filterversão é perfeitamente clara e tem muito menos ruído.
sepp2k,
9
o que está r.matchaqui?
rbatt
2
@rbatt r.matché um método que, quando aplicado a uma determinada string, descobre se a regex rcorresponde àquela string (e retorna um objeto de correspondência correspondente se for o caso, mas isso não importa neste caso, pois apenas nos importamos se o resultado é verdadeiro)
sepp2k
167

Exemplo completo (Python 3):
para Python 2.x, observe a nota abaixo

import re

mylist = ["dog", "cat", "wildcat", "thundercat", "cow", "hooo"]
r = re.compile(".*cat")
newlist = list(filter(r.match, mylist)) # Read Note
print(newlist)

Impressões:

['cat', 'wildcat', 'thundercat']

Nota:

Para desenvolvedores Python 2.x, filterjá retorna uma lista. No Python 3.xfilter foi alterado para retornar um iterador, então ele deve ser convertido para list(a fim de vê-lo bem impresso).

Exemplo de código Python 3 Exemplo de código
Python 2.x

Mercúrio
fonte
4
Olá, Quando executo o código acima, recebo <filter object at 0x1057acda0>O que estou fazendo de errado?
1
De acordo com a documentação do python (python 2.7.12): docs.python.org/2/library/functions.html#filter filter retorna uma lista, não um objeto. Você também pode verificar esse código: repl.it/X3G/5786 (basta clicar em executar)
Mercury
1
Obrigado. Estou usando o Python 3.5.2 em um Mac. Tentei seu link. Claro que funciona, embora não saiba por que recebo essa mensagem. Eu até removi o strpois filterretorna uma lista de qualquer maneira, sem sucesso ...
4
@joshua você provavelmente já percebeu isso, mas tente print(list(newlist))ouprint([i for i in newlist])
James Draper
1
Isso é ridiculamente difícil. É por isso que R é superior. Simplesmente grep (pattern, vector_of_names)
MadmanLee de
1

Para fazer isso sem compilar o Regex primeiro, use uma lambdafunção - por exemplo:

from re import match

values = ['123', '234', 'foobar']
filtered_values = list(filter(lambda v: match('^\d+$', v), values))

print(filtered_values)

Retorna:

['123', '234']

filter()apenas pega a callablecomo primeiro argumento e retorna uma lista em que aquele chamável retornou um valor 'verdadeiro'.

Collin Heist
fonte