J'ai une liste composée de 20000 listes. J'utilise le troisième élément de chaque liste comme indicateur. 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 au moins le drapeau d'un élément est 0:
def check(list_):
for item in list_:
if item[2] == 0:
return True
return False
Si je check(my_list)
reviens True
, je continue à 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 au fur et à mesure que je le répétais, mais je ne suis pas autorisé à supprimer des éléments au fur et à mesure que je le répète.
Ma liste d'origine n'avait pas de drapeaux:
my_list = [["a", "b"], ["c", "d"], ["e", "f"], .....]
Étant donné que je ne pouvais pas supprimer des éléments pendant que je le répétais, j'ai inventé ces drapeaux. Mais le my_list
contient de nombreux éléments, et la while
boucle les lit tous à chaque for
boucle, et cela prend beaucoup de temps! Avez-vous des suggestions?
la source
None
ou au[]
fur et à mesure que vous parcourez la liste au lieu de les supprimer. Vérifier toute la liste avec «check ()» en itérant sur tous les éléments avant chaque passage sur la boucle intérieure est une approche très lente.Réponses:
La meilleure réponse ici est d'utiliser
all()
, qui est la fonction intégrée à cette situation. Nous combinons cela avec une expression de générateur pour produire le résultat souhaité de manière propre et efficace. Par exemple:Notez que
all(flag == 0 for (_, _, flag) in items)
c'est directement équivalent àall(item[2] == 0 for item in items)
, c'est juste un peu plus agréable à lire dans ce cas.Et, pour l'exemple de filtre, une compréhension de liste (bien sûr, vous pouvez utiliser une expression de générateur le cas échéant):
Si vous voulez vérifier qu'au moins un élément est 0, la meilleure option est d'utiliser
any()
ce qui est plus lisible:la source
all()
et à mesure desany()
courts-circuits, si, par exemple, la première valeur sur la mienne est évaluéeFalse
,all()
échouera et ne vérifiera plus de valeurs, en revenantFalse
. Votre exemple fera de même, sauf qu'il générera d'abord la liste complète des comparaisons, ce qui signifie beaucoup de traitement pour rien.Si vous souhaitez vérifier si un élément de la liste ne respecte pas une condition, utilisez
all
:Pour supprimer tous les éléments qui ne correspondent pas, utilisez
filter
la source
[...]
enall(...)
car il peut alors créer un générateur au lieu d'une liste, non seulement vous permet d' économiser deux personnages , mais enregistre également la mémoire et le temps. En utilisant des générateurs, un seul élément sera calculé à la fois (les anciens résultats seront supprimés car ils ne sont plus utilisés) et si l'un d'eux s'avèreFalse
, le générateur cessera de calculer le reste.Vous pouvez utiliser le protocole itertools comme ceci, il s'arrêtera dès qu'une condition est remplie qui échoue à votre déclaration. La méthode inverse serait abandonnée
la source
Une autre façon d'utiliser
itertools.ifilter
. Cela vérifie la véracité et le processus (en utilisantlambda
)Échantillon-
la source
cette façon est un peu plus flexible que d'utiliser
all()
:ou plus succinctement:
la source
all_zeros = False in [x[2] == 0 for x in my_list]
ou même0 in [x[2] for x in my_list]
et en conséquence pourany_zeros
? Je ne vois vraiment aucune amélioration remarquableall()
.all_zeros = False in [x[2] == 0 for x in my_list]
évaluéeFalse
, tandis que la mienne est évaluéeTrue
. Si vous le changez en,all_zeros = not (False in [x[2] == 0 for x in my_list])
il est équivalent au mien. Et0 in [x[2] for x in my_list]
ne va évidemment que travailler pourany_zeros
. Mais j'aime la brièveté de votre idée, donc je