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?
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
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
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)
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]
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