Eu tenho uma lista de valores que eu preciso filtrar dados os valores em uma lista de booleanos:
list_a = [1, 2, 4, 6]
filter = [True, False, True, False]
Eu gero uma nova lista filtrada com a seguinte linha:
filtered_list = [i for indx,i in enumerate(list_a) if filter[indx] == True]
o que resulta em:
print filtered_list
[1,4]
A linha funciona, mas parece (para mim) um pouco exagerada e eu queria saber se havia uma maneira mais simples de conseguir o mesmo.
Conselhos
Resumo de dois bons conselhos dados nas respostas abaixo:
1- Não nomeie uma lista filter
como eu fiz, porque é uma função interna.
2- Não compare as coisas True
como eu fiz, if filter[idx]==True..
pois é desnecessário. Basta usar if filter[idx]
é suficiente.
if filter[indx] == True
Você não usar==
se você quiser verificar se há identidade comTrue
, usois
. De qualquer forma, neste caso, toda a comparação é inútil, você pode simplesmente usarif filter[indx]
. Por fim: nunca use o nome de um built-in como um nome de variável / módulo (estou me referindo ao nomefilter
). Usando algo comoincluded
, para queif
leia bem (if included[indx]
).Respostas:
Você está procurando
itertools.compress
:Comparações de tempo (py3.x):
Não use
filter
como um nome de variável, é uma função interna.fonte
[2, 6]
?list(compress(list_a, [not i for i in fill]))
deve retornar[2, 6]
Igual a:
O uso
zip
é a maneira pitônica de iterar várias seqüências em paralelo, sem a necessidade de indexação. Isso pressupõe que as duas seqüências tenham o mesmo comprimento (o zip pára após o menor tempo). Usaritertools
para um caso tão simples é um pouco exagerado ...Uma coisa que você faz no seu exemplo que realmente deveria parar de fazer é comparar as coisas com True, isso geralmente não é necessário. Em vez de
if filter[idx]==True: ...
, você pode simplesmente escreverif filter[idx]: ...
.fonte
Com numpy:
ou veja a resposta de Alex Szatmary se list_a puder ser um array numpy, mas não filtrar
Numpy geralmente também oferece um grande aumento de velocidade
fonte
NumPy
maislist
possível. Mas se você precisar usar delist
qualquer maneira, você (usando aNumPy
solução) cria anp.array
partir de ambas as listas, usa a indexação booleana e finalmente converte a matriz de volta à lista com otolist()
método Para ser mais preciso, você deve incluir a criação desses objetos na comparação de tempos. Então, o usoitertools.compress
ainda será a solução mais rápida.Para fazer isso usando numpy, ou seja, se você tiver uma matriz
a
, em vez delist_a
:fonte
where
.fonte
Com o python 3, você pode usar
list_a[filter]
para obterTrue
valores. Para obterFalse
valores, uselist_a[~filter]
fonte