web-dev-qa-db-fra.com

Comment trouver la longueur d'un objet "filtre" dans python

>>> n = [1,2,3,4]

>>> filter(lambda x:x>3,n)
<filter object at 0x0000000002FDBBA8>

>>> len(filter(lambda x:x>3,n))
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    len(filter(lambda x:x>3,n))
TypeError: object of type 'filter' has no len()

Je n'ai pas pu obtenir la longueur de la liste que j'ai reçue. J'ai donc essayé de l'enregistrer dans une variable, comme ceci ...

>>> l = filter(lambda x:x>3,n)
>>> len(l)
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    len(l)
TypeError: object of type 'filter' has no len()

Au lieu d'utiliser une boucle, existe-t-il un moyen d'obtenir la longueur de cela?

45
Srichakradhar

Vous devez en quelque sorte parcourir l'objet filtre. Une façon consiste à le convertir en liste:

l = list(filter(lambda x: x > 3, n))

len(l)  # <--

Mais cela pourrait vaincre le point d'utiliser filter() en premier lieu, car vous pourriez le faire plus facilement avec une compréhension de liste:

l = [x for x in n if x > 3]

Encore une fois, len(l) renverra la longueur.

64
arshajii

C'est une vieille question, mais je pense que cette question a besoin d'une réponse en utilisant l'idéologie map-Reduce. Alors voilà:

from functools import reduce

def ilen(iterable):
    return reduce(lambda sum, element: sum + 1, iterable, 0)

ilen(filter(lambda x: x > 3, n))

C'est particulièrement bon si n ne tient pas dans la mémoire de l'ordinateur.

22
Al Hoo

Les docs pour python 3 disent qu'il retourne un itérateur

"Construisez un itérateur à partir des éléments d'itérable pour lesquels la fonction renvoie true."

Dans python 2, il a renvoyé une liste: voir ici . Vous aurez besoin d'itérer l'objet filtre pour trouver sa longueur.

10
doctorlove

La conversion d'un filtre en liste prendra de la mémoire supplémentaire, ce qui peut ne pas être acceptable pour de grandes quantités de données. Vous pouvez trouver la longueur de l'objet filtre sans le convertir en liste:

sum(1 for _ in filter(lambda x: x > 3, n))

3
Mohammad Banisaeid

Généralement, filter et reduce ne sont pas Pythonic.

@arshajii a cité cette solution:

len([x for x in n if x > 3])

C'est assez simple, mais ne décrit pas exactement ce que vous voulez faire, et cela fait une liste qui peut utiliser de la mémoire supplémentaire. Une meilleure solution utilise sum avec générateur:

sum(1 for x in n if x > 3)

(Voir plus sur le générateur ici: https://www.python.org/dev/peps/pep-0289/#rationale )

Cependant, sum avec générateur est en fait plus lent dans la plupart des cas à cause de l'implémentation (testé dans CPython 3.6.4):

In [1]: %timeit len([1 for x in range(10000000)])
356 ms ± 17.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [2]: %timeit sum(1 for x in range(10000000))
676 ms ± 7.05 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
3
Ian Lin