108 votes

Obtenir le nombre d'éléments d'une liste (ou d'un autre itérable) sous certaines conditions.

Supposons que j'ai une liste contenant un grand nombre d'éléments,

l = [ 1, 4, 6, 30, 2, ... ]

Je veux obtenir le nombre d'éléments de cette liste, où un élément satisfait à une certaine condition. Ma première pensée a été :

count = len([i for i in l if my_condition(l)])

Mais si la liste filtrée comporte également un grand nombre d'éléments, je pense que créer une nouvelle liste pour le résultat filtré n'est qu'un gaspillage de mémoire. Pour l'efficacité, IMHO, l'appel ci-dessus ne peut pas être meilleur que :

count = 0
for i in l:
    if my_condition(l):
        count += 1

Existe-t-il un moyen fonctionnel d'obtenir le nombre d'éléments qui satisfont à la condition sans générer une liste temporaire ?

133voto

DSM Points 71975

Vous pouvez utiliser un expression de générateur :

>>> l = [1, 3, 7, 2, 6, 8, 10]
>>> sum(1 for i in l if i % 4 == 3)
2

ou même

>>> sum(i % 4 == 3 for i in l)
2

qui utilise le fait que True == 1 y False == 0 .

Alternativement, vous pouvez utiliser itertools.imap (python 2) ou simplement map (python 3) :

>>> def my_condition(x):
...     return x % 4 == 3
... 
>>> sum(map(my_condition, l))
2

31voto

JohnJ Points 1984

Vous voulez un compréhension du générateur plutôt qu'une liste ici.

Par exemple,

l = [1, 4, 6, 7, 30, 2]

def my_condition(x):
    return x > 5 and x < 20

print sum(1 for x in l if my_condition(x))
# -> 2
print sum(1 for x in range(1000000) if my_condition(x))
# -> 14

Ou utilisez itertools.imap (même si je pense que les expressions explicites de liste et de générateur ont l'air un peu plus pythoniques).

Notez que, bien que cela ne soit pas évident à partir de l'interface de l sum Par exemple, vous pouvez composer des compréhensions de générateur de manière agréable. Par exemple,

inputs = xrange(1000000)      # In Python 3 and above, use range instead of xrange
odds = (x for x in inputs if x % 2)  # Pick odd numbers
sq_inc = (x**2 + 1 for x in odds)    # Square and add one
print sum(x/2 for x in sq_inc)       # Actually evaluate each one
# -> 83333333333500000

L'avantage de cette technique est que vous pouvez spécifier des étapes conceptuellement séparées dans le code sans forcer l'évaluation et le stockage en mémoire jusqu'à ce que le résultat final soit évalué.

12voto

Will Points 821

Cela peut également être fait en utilisant reduce si vous préférez la programmation fonctionnelle

reduce(lambda count, i: count + my_condition(i), l, 0)

De cette façon, vous ne faites qu'un seul passage et aucune liste intermédiaire n'est générée.

10voto

Jsdodgers Points 3791

Vous pourriez faire quelque chose comme :

l = [1,2,3,4,5,..]
count = sum(1 for i in l if my_condition(i))

qui ajoute simplement 1 pour chaque élément qui satisfait à la condition.

2voto

kkonrad Points 833
from itertools import imap
sum(imap(my_condition, l))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X