¿Cómo comprobar si todos los elementos de una lista coinciden con una condición?

Resuelto alwbtc asked hace 12 años • 5 respuestas

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 allpara realizar la iteración. Consulte ¿Cómo funcionan todas y cada una de las funciones de Python? para una explicación de ally 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 anyy allfuncionará, pero son posibles soluciones más eficientes.

alwbtc avatar May 19 '12 21:05 alwbtc
Aceptado

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
Gareth Latty avatar May 19 '2012 15:05 Gareth Latty

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)
Hampus Nilsson avatar May 19 '2012 14:05 Hampus Nilsson

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
Hedde van der Heide avatar May 19 '2012 14:05 Hedde van der Heide

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]
mulllhausen avatar Nov 08 '2015 09:11 mulllhausen