web-dev-qa-db-fra.com

Comment vérifier si tous les éléments d'une liste correspondent à une condition?

J'ai une liste composée d'environ 20000 listes. J'utilise le 3ème élément de chaque liste comme un drapeau. Je veux faire quelques opérations sur cette liste tant que le drapeau d'au moins un élément est 0, c'est comme:

my_list = [["a", "b", 0], ["c", "d", 0], ["e", "f", 0], .....]

Au début, tous les drapeaux sont 0. J'utilise une boucle while pour vérifier si le drapeau d'au moins un élément est 0:

def check(list_):
    for item in list_:
        if item[2] == 0:
            return True
    return False

Si check(my_list) retourne True, je continue de travailler sur ma liste:

while check(my_list):
    for item in my_list:
        if condition:
            item[2] = 1
        else:
            do_sth()

En fait, je voulais supprimer un élément de ma liste lorsque j'y ai itéré, mais je ne suis pas autorisé à en supprimer.

Ma liste d'origine n'avait pas de drapeaux:

my_list = [["a", "b"], ["c", "d"], ["e", "f"], .....]

Comme je ne pouvais pas supprimer les éléments en itérant, j'ai inventé ces drapeaux. Mais le my_list contient de nombreux éléments et la boucle while les lit tous à chaque boucle for, ce qui prend beaucoup de temps! Avez-vous des suggestions?

178
alwbtc

La meilleure réponse ici est d’utiliser all() , qui est le paramètre intégré à cette situation. Nous combinons cela avec une expression générateur pour produire le résultat souhaité de manière nette et efficace. Par exemple:

>>> items = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
>>> all(item[2] == 0 for item in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(item[2] == 0 for item in items)
False

Et, pour son exemple de filtre, une liste de compréhension:

>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]

Si vous voulez vérifier qu'au moins un élément est 0, la meilleure option est d'utiliser any() qui est plus lisible:

>>> any(item[2] == 0 for item in items)
True
345
Gareth Latty

Vous pouvez utiliser le takewhit d'itertools comme ceci, il s'arrêtera une fois qu'une condition est remplie qui échoue votre déclaration. La méthode opposée serait goutte à goutte

for x in itertools.takewhile(lambda x: x[2] == 0, list)
    print x
7

Si vous voulez vérifier si un élément de la liste ne respecte pas une condition, utilisez 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)

Pour supprimer tous les éléments ne correspondant pas, utilisez filter

# Will remove all elements where x[2] is 0
listb = filter(lambda x: x[2] != 0, listb)
6
Hampus Nilsson

cette méthode est un peu plus flexible que d'utiliser 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

ou plus succinctement:

all_zeros = not False in [x[2] == 0 for x in my_list]
any_zeros = 0 in [x[2] for x in my_list]
0
mulllhausen

Une autre façon d'utiliser itertools.ifilter. Ceci vérifie la véracité et le processus (en utilisant lambda)

Échantillon-

for x in itertools.ifilter(lambda x: x[2] == 0, my_list):
    print x
0
SIslam