¿Cómo comprobar si todos los elementos de una lista coinciden con una condición?
Tengo una lista que contiene muchas sublistas de 3 elementos cada una, como:
my_list = [["a", "b", 0], ["c", "d", 0], ["e", "f", 0], .....]
El último elemento de cada sublista es una especie de bandera, que inicialmente es 0 para cada sublista. A medida que avanza mi algoritmo, quiero comprobar si este indicador es 0 para al menos un elemento. Actualmente uso un bucle while, así:
def check(list_):
for item in list_:
if item[2] == 0:
return True
return False
El algoritmo general se repite siempre que se cumpla esa condición y establece algunas de las banderas en cada iteración:
while check(my_list):
for item in my_list:
if condition:
item[2] = 1
else:
do_sth()
Debido a que causa problemas eliminar elementos de la lista mientras se itera sobre ella, uso estos indicadores para realizar un seguimiento de los elementos que ya se han procesado.
¿Cómo puedo simplificar o acelerar el código?
Consulte también la forma pitónica de comprobar si una condición se cumple para cualquier elemento de una lista para comprobar la condición de cualquier elemento. Tenga en cuenta que "cualquier" y "todos" los cheques están relacionados mediante la ley de De Morgan , al igual que "o" y "y" están relacionados.
Las respuestas existentes aquí utilizan la función incorporada all
para realizar la iteración. Consulte ¿Cómo funcionan todas y cada una de las funciones de Python? para una explicación de all
y su contraparte, any
.
Si la condición que desea verificar es "se encuentra en otro contenedor", consulte ¿Cómo verificar si todos los elementos siguientes están en una lista? y su contraparte, ¿ Cómo comprobar si uno de los siguientes elementos está en una lista? . Usar any
y all
funcionará, pero son posibles soluciones más eficientes.
La mejor respuesta aquí es usar all()
, que es la versión integrada para esta situación. Combinamos esto con una expresión generadora para producir el resultado que desea de forma limpia y eficiente. Por ejemplo:
>>> items = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
False
Tenga en cuenta que all(flag == 0 for (_, _, flag) in items)
es directamente equivalente a all(item[2] == 0 for item in items)
, pero en este caso es un poco más agradable de leer.
Y, para el ejemplo de filtro, una lista por comprensión (por supuesto, podría usar una expresión generadora cuando corresponda):
>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]
Si desea verificar que al menos un elemento sea 0, la mejor opción es usar any()
cuál es más legible:
>>> any(flag == 0 for (_, _, flag) in items)
True
Si desea comprobar si algún elemento de la lista infringe una condición, utilice all
:
if all([x[2] == 0 for x in lista]):
# Will run if all elements in the list has x[2] = 0 (use not to invert if necessary)
Para eliminar todos los elementos que no coinciden, utilicefilter
# Will remove all elements where x[2] is 0
listb = filter(lambda x: x[2] != 0, listb)
Podría usar el take while de itertools de esta manera, se detendrá una vez que se cumpla una condición que no cumpla con su declaración. El método opuesto sería dejar caer.
for x in itertools.takewhile(lambda x: x[2] == 0, list)
print x
de esta manera es un poco más flexible que usar all()
:
my_list = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
all_zeros = False if False in [x[2] == 0 for x in my_list] else True
any_zeros = True if True in [x[2] == 0 for x in my_list] else False
o más sucintamente:
all_zeros = not False in [x[2] == 0 for x in my_list]
any_zeros = 0 in [x[2] for x in my_list]