@Ivo, ninguna de esas declaraciones es cierta. Nunca debe modificar una lista sobre la que está iterando for x in listsi está usando una, while loopentonces está bien. el bucle demostrado eliminará cadenas vacías hasta que no haya más cadenas vacías y luego se detendrá. En realidad, ni siquiera había mirado la pregunta (solo el título), ¡pero respondí exactamente con el mismo bucle como una posibilidad! Si no desea utilizar comprensiones o filtros por el bien de la memoria, es una solución muy pitónica.
aaronasterling
44
Sigue siendo un punto muy válido para nunca cambiar la lista sobre la que estás iterando :)
Eduard Luca
1
@EduardLuca si el punto de iterar sobre una lista es cambiarla, entonces eso es lo contrario de lo que debe hacer. Solo debe tener cuidado de saber que no causa un comportamiento inesperado al hacerlo.
JFA
1
@EduardLuca, @JFA: El punto es que NO está iterando sobre ninguna lista. Lo haría si hubiera escrito algo en el formulario for var in list:, pero aquí, ha escrito while const in list:. que no está iterando sobre nada. solo está repitiendo el mismo código hasta que una condición sea falsa.
Si está tan presionado por el rendimiento, itertool'sifilter es aún más 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
44
@cpburnz Muy cierto. Sin embargo, con los ifilterresultados evaluados perezosamente, no de una sola vez, diría que para la mayoría de los casos ifilteres mejor. Es interesante que el uso filtersea aún más rápido que envolver un ifilteren un listpensamiento.
Humphrey Bogart
3
Si hace esto en una lista de números, tenga en cuenta que los ceros también se eliminarán (nota: solo utilicé los primeros 3 métodos), por lo que necesitará un método alternativo.
SnoringFrog
2
Esto se centra solo en la velocidad, no en lo pitónica que es la solución (la pregunta que se hizo). Las comprensiones de listas son la solución pitónica, y el filtro solo debe usarse si el perfil ha demostrado que listcomp es un cuello de botella.
Tritium21
3
@ quien-menciona-sobre-o-implica-Python-3, solo edite y actualice la respuesta. Solo estábamos discutiendo para Python 2 cuando se hizo esta pregunta, incluso Python 3 se lanzó casi 2 años. Pero actualice los resultados de Python 2 y 3.
Me gusta esta solución porque es fácilmente adaptable. Si necesitaba eliminar no sólo las cadenas vacías, pero las cadenas que son sólo espacios en blanco, por ejemplo: [x for x in strings if x.strip()].
Bono
67
filtro en realidad tiene una opción especial para esto:
filter(None, sequence)
Filtrará todos los elementos que evalúen a False. No es necesario usar una llamada real aquí como bool, len, etc.
Este es un idioma de pitón, de hecho. También es la única vez que todavía uso filter (), las comprensiones de listas se han apoderado de todos los demás.
no funcionará si tienes espacio entre la cadena de una palabra. por ejemplo: ['hola mundo', '', 'hola', '']. >> ['helloworld', '', 'hello', ''] ¿tiene alguna otra solución para mantener espacios dentro de un elemento en la lista pero eliminando otros?
Reihan_amn
Tenga en cuenta que filter(None, lstr)no elimina cadenas vacías con un espacio' ' Sí, porque esa no es una cadena vacía.
AMC
15
La respuesta de @ Ib33X es increíble. Si desea eliminar cada cadena vacía, después de despojado. necesitas usar el método de tira también. De lo contrario, también devolverá la cadena vacía si tiene espacios en blanco. Me gusta, "" también será válido para esa respuesta. Entonces, se puede lograr por.
strings =["first","","second "," "][x.strip()for x in strings if x.strip()]
La respuesta para esto será ["first", "second"].
Si desea utilizar el filtermétodo en su lugar, puede hacer me gusta
list(filter(lambda item: item.strip(), strings)). Esto es dar el mismo resultado.
En lugar de if x, usaría if X! = '' Para eliminar cadenas vacías. Me gusta esto:
str_list =[x for x in str_list if x !='']
Esto conservará el tipo de datos Ninguno dentro de su lista. Además, en caso de que su lista tenga enteros y 0 sea uno de ellos, también se conservará.
Por ejemplo,
str_list =[None,'',0,"Hi",'',"Hello"][x for x in str_list if x !=''][None,0,"Hi","Hello"]
Si sus listas tienen tipos dispares (excepto Ninguno), puede tener un problema mayor.
Tritium21
¿Qué tipos? Intenté con int y otros tipos numéricos, cadenas, listas, tupes, conjuntos y Ninguno y sin problemas. Pude ver que si hay algún tipo definido por el usuario que no sea compatible con el método str podría dar un problema. ¿Debería estar preocupado por cualquier otro?
thiruvenkadam
1
Si tiene una str_list = [None, '', 0, "Hi", '', "Hello"], es un signo de una aplicación mal diseñada. No debe tener más de una interfaz (tipo) y Ninguna en la misma lista.
Tritium21
3
¿Recuperando datos de db? ¿Lista de argumentos para una función mientras se realizan pruebas automatizadas?
thiruvenkadam
3
Esas suelen ser tuplas.
Tritium21
7
Dependiendo del tamaño de su lista, puede ser más eficiente si usa list.remove () en lugar de crear una nueva lista:
l =["1","","3",""]whileTrue:try:
l.remove("")exceptValueError:break
Esto tiene la ventaja de no crear una nueva lista, pero la desventaja de tener que buscar desde el principio cada vez, aunque a diferencia de usar while '' in lcomo se propuso anteriormente, solo requiere buscar una vez por ocurrencia ''(ciertamente hay una manera de mantener lo mejor de ambos métodos, pero es más complicado).
Puede editar la lista en su lugar haciendo ary[:] = [e for e in ary if e]. Mucho más limpio y no utiliza excepciones para controlar el flujo.
Krzysztof Karski
2
Bueno, eso no está realmente "en su lugar". Estoy bastante seguro de que esto crea una nueva lista y simplemente la asigna al nombre del anterior.
Andrew Jaffe
Esto funciona muy mal ya que la cola de datos se baraja en la memoria en cada eliminación. Es mejor eliminar todo en un solo golpe.
wim
7
Tenga en cuenta que si desea mantener los espacios en blanco dentro de una cadena , puede eliminarlos involuntariamente utilizando algunos enfoques. Si tienes esta lista
['hola mundo', '', '', 'hola'] lo que quieras ['hola mundo', 'hola']
primero recorte la lista para convertir cualquier tipo de espacio en blanco en una cadena vacía:
space_to_empty =[x.strip()for x in _text_list]
luego elimine la cadena vacía de la lista
space_clean_list =[x for x in space_to_empty if x]
Si desea mantener los espacios en blanco dentro de una cadena, puede eliminarlos involuntariamente utilizando algunos enfoques. ¿Te gusta este enfoque, entonces?
AMC
Gracias amigo, funcionó para mí con un pequeño cambio. es decirspace_clean_list = [x.strip() for x in y if x.strip()]
Muhammad Mehran Khan Attari
6
Uso filter:
newlist=filter(lambda x: len(x)>0, oldlist)
Los inconvenientes de usar el filtro como se señaló es que es más lento que las alternativas; además,lambda suele ser costoso.
O puede optar por el más simple y el más 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
Este es el más intuitivo de los métodos y lo hace en un tiempo decente.
Bienvenido a SO. No has sido ignorado. Usted no ha sido atacado por ningún votante no homónimo. Le han dado su opinión. Amplificación: Su primer argumento propuesto para filtro es peor que lambda x: len(x)cuál es peor que lambda x : xcuál es la peor de las 4 soluciones en la respuesta seleccionada. Se prefiere el funcionamiento correcto, pero no es suficiente. Pase el cursor sobre el botón de votación negativa: dice "Esta respuesta no es útil".
John Machin el
5
Según lo informado por Aziz Altofilter(None, lstr) , no elimina las cadenas vacías con un espacio, ' 'pero si está seguro de que lstr contiene solo cadenas, puede usarfilter(str.strip, lstr)
s and s.strip()se puede simplificar a solo s.strip().
AMC
s and s.strip()es necesario si queremos replicar completamente filter(None, words), la respuesta aceptada. Corregí las funciones de muestra x2 anteriores y eliminé las x2 malas.
ankostis
-2
Para una lista con una combinación de espacios y valores vacíos, use la comprensión simple de la lista:
>>> s =['I','am','a','','great',' ','',' ','person','!!','Do','you','think','its','a','','a','','joke','',' ','','?','','','','?']
Entonces, puede ver, esta lista tiene una combinación de espacios y elementos nulos. Usando el fragmento -
>>> 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
si está usando una,while loop
entonces está bien. el bucle demostrado eliminará cadenas vacías hasta que no haya más cadenas vacías y luego se detendrá. En realidad, ni siquiera había mirado la pregunta (solo el título), ¡pero respondí exactamente con el mismo bucle como una posibilidad! Si no desea utilizar comprensiones o filtros por el bien de la memoria, es una solución muy pitónica.for var in list:
, pero aquí, ha escritowhile const in list:
. que no está iterando sobre nada. solo está repitiendo el mismo código hasta que una condición sea falsa.Respuestas:
Yo usaría
filter
:Python 3 devuelve un iterador de
filter
, por lo que debe incluirse en una llamada alist()
fuente
itertool
'sifilter
es aún más 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 evaluados perezosamente, no de una sola vez, diría que para la mayoría de los casosifilter
es mejor. Es interesante que el usofilter
sea aún más rápido que envolver unifilter
en unlist
pensamiento.Usar una lista de comprensión es la forma más pitónica:
Si la lista debe modificarse en el lugar, porque hay otras referencias que deben ver los datos actualizados, utilice una asignación de segmento:
fuente
[x for x in strings if x.strip()]
.filtro en realidad tiene una opción especial para esto:
Filtrará todos los elementos que evalúen a False. No es necesario usar una llamada real aquí como bool, len, etc.
Es igual de rápido que el mapa (bool, ...)
fuente
Comparar tiempo
Tenga en cuenta que
filter(None, lstr)
no elimina las cadenas vacías con un espacio' '
, solo elimina''
mientras' '.join(lstr).split()
elimina las dos.Para usar
filter()
con las cadenas de espacio en blanco eliminadas, lleva mucho más tiempo:fuente
filter(None, lstr)
no elimina cadenas vacías con un espacio' '
Sí, porque esa no es una cadena vacía.La respuesta de @ Ib33X es increíble. Si desea eliminar cada cadena vacía, después de despojado. necesitas usar el método de tira también. De lo contrario, también devolverá la cadena vacía si tiene espacios en blanco. Me gusta, "" también será válido para esa respuesta. Entonces, se puede lograr por.
La respuesta para esto será
["first", "second"]
.Si desea utilizar el
filter
método en su lugar, puede hacer me gustalist(filter(lambda item: item.strip(), strings))
. Esto es dar el mismo resultado.fuente
En lugar de if x, usaría if X! = '' Para eliminar cadenas vacías. Me gusta esto:
Esto conservará el tipo de datos Ninguno dentro de su lista. Además, en caso de que su lista tenga enteros y 0 sea uno de ellos, también se conservará.
Por ejemplo,
fuente
str_list = [None, '', 0, "Hi", '', "Hello"]
, es un signo de una aplicación mal diseñada. No debe tener más de una interfaz (tipo) y Ninguna en la misma lista.Dependiendo del tamaño de su lista, puede ser más eficiente si usa list.remove () en lugar de crear una nueva lista:
Esto tiene la ventaja de no crear una nueva lista, pero la desventaja de tener que buscar desde el principio cada vez, aunque a diferencia de usar
while '' in l
como se propuso anteriormente, solo requiere buscar una vez por ocurrencia''
(ciertamente hay una manera de mantener lo mejor de ambos métodos, pero es más complicado).fuente
ary[:] = [e for e in ary if e]
. Mucho más limpio y no utiliza excepciones para controlar el flujo.Tenga en cuenta que si desea mantener los espacios en blanco dentro de una cadena , puede eliminarlos involuntariamente utilizando algunos enfoques. Si tienes esta lista
['hola mundo', '', '', 'hola'] lo que quieras ['hola mundo', 'hola']
primero recorte la lista para convertir cualquier tipo de espacio en blanco en una cadena vacía:
luego elimine la cadena vacía de la lista
fuente
space_clean_list = [x.strip() for x in y if x.strip()]
Uso
filter
:Los inconvenientes de usar el filtro como se señaló es que es más lento que las alternativas; además,
lambda
suele ser costoso.O puede optar por el más simple y el más iterativo de todos:
Este es el más intuitivo de los métodos y lo hace en un tiempo decente.
fuente
lambda x: len(x)
cuál es peor quelambda x : x
cuál es la peor de las 4 soluciones en la respuesta seleccionada. Se prefiere el funcionamiento correcto, pero no es suficiente. Pase el cursor sobre el botón de votación negativa: dice "Esta respuesta no es útil".Según lo informado por Aziz Alto
filter(None, lstr)
, no elimina las cadenas vacías con un espacio,' '
pero si está seguro de que lstr contiene solo cadenas, puede usarfilter(str.strip, lstr)
Comparar el tiempo en mi pc
La solución más rápida para eliminar
''
y vaciar cadenas con un espacio' '
permanece' '.join(lstr).split()
.Como se informó en un comentario, la situación es diferente si sus cadenas contienen espacios.
Puede ver que
filter(str.strip, lstr)
preserva las cadenas con espacios, pero' '.join(lstr).split()
dividirá estas cadenas.fuente
join
solución dividirá las cadenas con espacio pero el filtro no lo hará. Gracias por tu comentario, mejoré mi respuesta.Resuma las mejores respuestas:
1. Eliminar emtpties SIN pelar:
Es decir, las cadenas de todo el espacio se retienen:
PRO:
2. Para eliminar los vacíos después de pelar ...
2.a ... cuando las cadenas NO contienen espacios entre palabras:
PRO:
2.b ... cuando las cadenas contienen espacios entre palabras?
PRO:
Puntos de referencia en una máquina 2018:
fuente
s and s.strip()
se puede simplificar a solos.strip()
.s and s.strip()
es necesario si queremos replicar completamentefilter(None, words)
, la respuesta aceptada. Corregí las funciones de muestra x2 anteriores y eliminé las x2 malas.Para una lista con una combinación de espacios y valores vacíos, use la comprensión simple de la lista:
Entonces, puede ver, esta lista tiene una combinación de espacios y elementos nulos. Usando el fragmento -
fuente