@Vo, nenhuma dessas afirmações é verdadeira. Você nunca deve modificar uma lista que for x in listvocê está usando repetidamente. Se você estiver usando um while loop, tudo bem. o loop demonstrado removerá cadeias vazias até que não haja mais cadeias vazias e depois pare. Na verdade, eu nem sequer olhei para a pergunta (apenas o título), mas respondi exatamente com o mesmo loop que uma possibilidade! Se você não deseja usar compreensões ou filtros para fins de memória, é uma solução muito pitônica.
Aaronasterling 02/10/10
4
Ainda um ponto muito válido nunca alterar a lista que você está interagindo sobre :)
Eduard Luca
1
@EduardLuca se o objetivo de iterar sobre uma lista for alterá-la, é o contrário do que você deve fazer. Você só precisa ter cuidado para saber que não causa um comportamento inesperado ao fazê-lo.
JFA 01/04
1
@EduardLuca, @JFA: O ponto é que ele NÃO está iterando sobre nenhuma lista. Ele escreveria se tivesse escrito algo na forma for var in list:, mas aqui, ele escreveu while const in list:. que não está iterando sobre nada. é apenas repetir o mesmo código até que uma condição seja falsa.
Se você é tão pressionado pelo desempenho, itertooloifilter é ainda mais rápido >>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)2.3468542098999023; >>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)0.04442191123962402.
Humphrey Bogart
4
@cpburnz Muito verdade. No entanto, com os ifilterresultados são avaliados preguiçosamente, não de uma só vez - eu diria que, na maioria dos casos, ifilteré melhor. Interessante que o uso filterainda é mais rápido do que envolver um ifilterem um listpensamento.
Humphrey Bogart
3
Se você fizer isso em uma lista de números, observe que os zeros também serão removidos (nota: usei apenas os três primeiros métodos); portanto, você precisará de um método alternativo.
precisa saber é o seguinte
2
Isso se concentra apenas na velocidade, não em quão pitônica é a solução (a pergunta que foi feita). As compreensões de lista são a solução pitônica e o filtro deve ser usado apenas se a criação de perfil provar que o listcomp é um gargalo.
Tritium21
3
@ quem mencionar sobre Python-3 ou implicar-3, basta editar e atualizar a resposta. Estávamos discutindo apenas para o Python 2 quando essa pergunta foi feita, até o Python 3 foi lançado por quase 2 anos. Mas atualize os resultados do Python 2 e 3.
Eu gosto desta solução porque é facilmente adaptável. Se eu precisava para remover não apenas strings vazias, mas cordas que são apenas espaços em branco, por exemplo: [x for x in strings if x.strip()].
Bond
67
filtro realmente tem uma opção especial para isso:
filter(None, sequence)
Ele filtrará todos os elementos que avaliarem como Falso. Não há necessidade de usar uma chamada real aqui, como bool, len e assim por diante.
Observe que filter(None, lstr)não remove seqüências de caracteres vazias com um espaço ' ', apenas remove-as ''enquanto ' '.join(lstr).split()remove as duas.
Para usar filter()com as cadeias de espaço em branco removidas, leva muito mais tempo:
>>> timeit('filter(None, [l.replace(" ", "") for l in lstr])',"lstr=['hello', '', ' ', 'world', ' ']", number=10000000)18.101892948150635
não funcionará se você tiver espaço entre a sequência de uma palavra. por exemplo: ['olá mundo', '', 'olá', '']. >> ['helloworld', '', 'hello', ''] você tem outra solução para manter espaços dentro de um item da lista, mas remover outros?
Reihan_amn
Observe que filter(None, lstr)não remove cadeias vazias com um espaço' ' Sim, porque não é uma cadeia vazia.
AMC
15
A resposta de @ Ib33X is awesome. Se você deseja remover todas as cordas vazias, depois de retiradas. você precisa usar o método strip também. Caso contrário, ele retornará a sequência vazia também se tiver espaços em branco. Como "" também será válido para essa resposta. Então, pode ser alcançado por.
strings =["first","","second "," "][x.strip()for x in strings if x.strip()]
A resposta para isso será ["first", "second"].
Se você deseja usar o filtermétodo, pode fazer o mesmo
list(filter(lambda item: item.strip(), strings)). Este é o mesmo resultado.
Se suas listas tiverem tipos diferentes (exceto Nenhum), você poderá ter um problema maior.
Tritium21
Quais tipos? Eu tentei com int e outros tipos numéricos, seqüências de caracteres, listas, tupes, conjuntos e nenhum e nenhum problema lá. Pude ver que, se houver algum tipo definido pelo usuário que não suporte o método str, isso pode causar um problema. Eu deveria estar preocupado com outro?
thiruvenkadam 23/02
1
Se você tiver um str_list = [None, '', 0, "Hi", '', "Hello"], é um sinal de um aplicativo mal projetado. Você não deve ter mais de uma interface (tipo) e Nenhuma na mesma lista.
Tritium21
3
Recuperando dados do db? lista de argumentos para uma função durante o teste automatizado?
238156 thirteenkadam
3
Geralmente são tuplas.
Tritium21
7
Dependendo do tamanho da sua lista, pode ser mais eficiente se você usar list.remove () em vez de criar uma nova lista:
l =["1","","3",""]whileTrue:try:
l.remove("")exceptValueError:break
Isso tem a vantagem de não criar uma nova lista, mas a desvantagem de ter que pesquisar desde o início de cada vez, embora, ao contrário do while '' in lque foi proposto acima, requer apenas uma pesquisa por ocorrência de ''(certamente existe uma maneira de manter o melhor ambos os métodos, mas é mais complicado).
se você quiser manter os espaços em branco em uma string, remova-os sem querer usando algumas abordagens. Como esta abordagem, então?
AMC
Obrigado cara, funcionou para mim com uma pequena mudança. iespace_clean_list = [x.strip() for x in y if x.strip()]
Muhammad Mehran Khan Attari
6
Use filter:
newlist=filter(lambda x: len(x)>0, oldlist)
As desvantagens de usar o filtro, conforme apontado, é que ele é mais lento que as alternativas; Além disso, lambdageralmente é caro.
Ou você pode optar pelo mais simples e mais iterativo de todos:
# I am assuming listtext is the original list containing (possibly) empty itemsfor item in listtext:if item:
newlist.append(str(item))# You can remove str() based on the content of your original list
esse é o método mais intuitivo e o faz em tempo decente.
Bem-vindo ao SO. Você não foi ignorado. Você não foi atacado por um downvoter desagradável. Você recebeu feedback. Amplificação: o primeiro argumento proposto para o filtro é pior do lambda x: len(x)que lambda x : xo pior e a pior das 4 soluções na resposta selecionada. O funcionamento correto é preferido, mas não suficiente. Passe o cursor sobre o botão de voto negativo: ele diz "Esta resposta não é útil".
John Machin 11/01
5
Conforme relatado por Aziz Altofilter(None, lstr) , não remove cadeias vazias com um espaço, ' 'mas se você tiver certeza de que o lstr contém apenas cadeias, você pode usarfilter(str.strip, lstr)
Isso funciona apenas se suas seqüências de caracteres não contiverem espaços. Caso contrário, você também estará dividindo essas strings.
phillyslick
1
A @BenPolinsky, como você relatou, a joinsolução dividirá as strings com espaço, mas o filtro não. Obrigado pelo seu comentário, melhorei minha resposta.
Paolo Melchiorre
-1
Resuma as melhores respostas:
1. Eliminar vazios SEM remover:
Ou seja, as seqüências de todos os espaços são mantidas:
slist = list(filter(None, slist))
PROs:
mais simples;
mais rápido (veja os benchmarks abaixo).
2. Para eliminar vazios após a remoção ...
2.a ... quando as strings NÃO contêm espaços entre as palavras:
slist =' '.join(slist).split()
PROs:
código pequeno
rápido (mas não mais rápido com grandes conjuntos de dados devido à memória, ao contrário do que resulta em @ paolo-melchiorre)
2.b ... quando strings contêm espaços entre as palavras?
slist = list(filter(str.strip, slist))
PROs:
o mais rápido;
compreensibilidade do código.
Benchmarks em uma máquina de 2018:
## Build test-data#import random, string
nwords =10000
maxlen =30
null_ratio =0.1
rnd = random.Random(0)# deterministic results
words =[' '* rnd.randint(0, maxlen)if rnd.random()>(1- null_ratio)else''.join(random.choices(string.ascii_letters, k=rnd.randint(0, maxlen)))for _i in range(nwords)]## Test functions#def nostrip_filter(slist):return list(filter(None, slist))def nostrip_comprehension(slist):return[s for s in slist if s]def strip_filter(slist):return list(filter(str.strip, slist))def strip_filter_map(slist):return list(filter(None, map(str.strip, slist)))def strip_filter_comprehension(slist):# waste memoryreturn list(filter(None,[s.strip()for s in slist]))def strip_filter_generator(slist):return list(filter(None,(s.strip()for s in slist)))def strip_join_split(slist):# words without(!) spacesreturn' '.join(slist).split()## Benchmarks#%timeit nostrip_filter(words)142µs ±16.8µs per loop (mean ± std. dev. of 7 runs,10000 loops each)%timeit nostrip_comprehension(words)263µs ±19.1µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter(words)653µs ±37.5µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_map(words)642µs ±36µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_comprehension(words)693µs ±42.2µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_generator(words)750µs ±28.6µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_join_split(words)796µs ±103µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
s and s.strip()pode ser simplificado para apenas s.strip().
AMC
s and s.strip() é necessário se quisermos replicar completamente filter(None, words) , a resposta aceita. Corrigi x2 funções de amostra acima e larguei x2 más.
ankostis 10/01
-2
Para uma lista com uma combinação de espaços e valores vazios, use a compreensão simples da lista -
>>> s =['I','am','a','','great',' ','',' ','person','!!','Do','you','think','its','a','','a','','joke','',' ','','?','','','','?']
Então, como você pode ver, esta lista possui uma combinação de espaços e elementos nulos. Usando o snippet -
>>> d =[x for x in s if x.strip()]>>> d
>>> d =['I','am','a','great','person','!!','Do','you','think','its','a','a','joke','?','?']
for x in list
você está usando repetidamente. Se você estiver usando umwhile loop
, tudo bem. o loop demonstrado removerá cadeias vazias até que não haja mais cadeias vazias e depois pare. Na verdade, eu nem sequer olhei para a pergunta (apenas o título), mas respondi exatamente com o mesmo loop que uma possibilidade! Se você não deseja usar compreensões ou filtros para fins de memória, é uma solução muito pitônica.for var in list:
, mas aqui, ele escreveuwhile const in list:
. que não está iterando sobre nada. é apenas repetir o mesmo código até que uma condição seja falsa.Respostas:
Eu usaria
filter
:Python 3 retorna um iterador de
filter
, portanto, deve ser agrupado em uma chamada paralist()
fonte
itertool
oifilter
é ainda mais rápido>>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
2.3468542098999023
;>>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)
0.04442191123962402
.ifilter
resultados são avaliados preguiçosamente, não de uma só vez - eu diria que, na maioria dos casos,ifilter
é melhor. Interessante que o usofilter
ainda é mais rápido do que envolver umifilter
em umlist
pensamento.Usar uma compreensão de lista é a maneira mais pitônica:
Se a lista precisar ser modificada no local, porque existem outras referências que devem ver os dados atualizados, use uma atribuição de fatia:
fonte
[x for x in strings if x.strip()]
.filtro realmente tem uma opção especial para isso:
Ele filtrará todos os elementos que avaliarem como Falso. Não há necessidade de usar uma chamada real aqui, como bool, len e assim por diante.
É igualmente rápido como mapa (bool, ...)
fonte
Compare tempo
Observe que
filter(None, lstr)
não remove seqüências de caracteres vazias com um espaço' '
, apenas remove-as''
enquanto' '.join(lstr).split()
remove as duas.Para usar
filter()
com as cadeias de espaço em branco removidas, leva muito mais tempo:fonte
filter(None, lstr)
não remove cadeias vazias com um espaço' '
Sim, porque não é uma cadeia vazia.A resposta de @ Ib33X is awesome. Se você deseja remover todas as cordas vazias, depois de retiradas. você precisa usar o método strip também. Caso contrário, ele retornará a sequência vazia também se tiver espaços em branco. Como "" também será válido para essa resposta. Então, pode ser alcançado por.
A resposta para isso será
["first", "second"]
.Se você deseja usar o
filter
método, pode fazer o mesmolist(filter(lambda item: item.strip(), strings))
. Este é o mesmo resultado.fonte
Em vez de se x, eu usaria se X! = '' Para eliminar apenas cadeias vazias. Como isso:
Isso preservará Nenhum tipo de dados em sua lista. Além disso, caso sua lista tenha números inteiros e 0 seja um deles, ela também será preservada.
Por exemplo,
fonte
str_list = [None, '', 0, "Hi", '', "Hello"]
, é um sinal de um aplicativo mal projetado. Você não deve ter mais de uma interface (tipo) e Nenhuma na mesma lista.Dependendo do tamanho da sua lista, pode ser mais eficiente se você usar list.remove () em vez de criar uma nova lista:
Isso tem a vantagem de não criar uma nova lista, mas a desvantagem de ter que pesquisar desde o início de cada vez, embora, ao contrário do
while '' in l
que foi proposto acima, requer apenas uma pesquisa por ocorrência de''
(certamente existe uma maneira de manter o melhor ambos os métodos, mas é mais complicado).fonte
ary[:] = [e for e in ary if e]
. Muito mais limpo e não usa exceções para o fluxo de controle.Lembre-se de que, se você quiser manter os espaços em branco em uma string , remova-os sem querer usando algumas abordagens. Se você tem esta lista
['olá mundo', '', '', 'olá']] o que você pode querer ['olá mundo', 'olá']
primeiro apare a lista para converter qualquer tipo de espaço em branco em string vazia:
em seguida, remova a string vazia da lista deles
fonte
space_clean_list = [x.strip() for x in y if x.strip()]
Use
filter
:As desvantagens de usar o filtro, conforme apontado, é que ele é mais lento que as alternativas; Além disso,
lambda
geralmente é caro.Ou você pode optar pelo mais simples e mais iterativo de todos:
esse é o método mais intuitivo e o faz em tempo decente.
fonte
lambda x: len(x)
quelambda x : x
o pior e a pior das 4 soluções na resposta selecionada. O funcionamento correto é preferido, mas não suficiente. Passe o cursor sobre o botão de voto negativo: ele diz "Esta resposta não é útil".Conforme relatado por Aziz Alto
filter(None, lstr)
, não remove cadeias vazias com um espaço,' '
mas se você tiver certeza de que o lstr contém apenas cadeias, você pode usarfilter(str.strip, lstr)
Compare o tempo no meu pc
A solução mais rápida para remover
''
e esvaziar cordas com um espaço' '
permanece' '.join(lstr).split()
.Conforme relatado em um comentário, a situação será diferente se suas sequências contiverem espaços.
Você pode ver que
filter(str.strip, lstr)
preserva as strings com espaços, mas as' '.join(lstr).split()
dividirá.fonte
join
solução dividirá as strings com espaço, mas o filtro não. Obrigado pelo seu comentário, melhorei minha resposta.Resuma as melhores respostas:
1. Eliminar vazios SEM remover:
Ou seja, as seqüências de todos os espaços são mantidas:
PROs:
2. Para eliminar vazios após a remoção ...
2.a ... quando as strings NÃO contêm espaços entre as palavras:
PROs:
2.b ... quando strings contêm espaços entre as palavras?
PROs:
Benchmarks em uma máquina de 2018:
fonte
s and s.strip()
pode ser simplificado para apenass.strip()
.s and s.strip()
é necessário se quisermos replicar completamentefilter(None, words)
, a resposta aceita. Corrigi x2 funções de amostra acima e larguei x2 más.Para uma lista com uma combinação de espaços e valores vazios, use a compreensão simples da lista -
Então, como você pode ver, esta lista possui uma combinação de espaços e elementos nulos. Usando o snippet -
fonte