89
>>> 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()

I could not get the length of the list I got. So I tried saving it to a variable, like this...

>>> 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()

Instead of using a loop, is there any way to get the length of this?

Srichakradhar
  • 1,535
  • 1
  • 12
  • 24
  • There is no way to know how many objects a generator will yield before it yields them. If you care about optimization, you can use _a priori_ information to speed things up - i.e. if you know that your list is sorted you can discard items below `index(3)`. – roippi Oct 04 '13 at 13:25

6 Answers6

123

You have to iterate through the filter object somehow. One way is to convert it to a list:

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

len(l)  # <--

But that might defeat the point of using filter() in the first place, since you could do this more easily with a list comprehension:

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

Again, len(l) will return the length.

arshajii
  • 127,459
  • 24
  • 238
  • 287
  • 4
    This is the simpliest way but not really the proper way. I prefer the answer of Al Hoo and tso . What a pity that python didn't internally support the reduce way! – Ben Sep 24 '17 at 17:21
  • 3
    This solution takes a lot of extra memory if `n` is quite large. – Mohammad Banisaeid Jul 14 '18 at 06:33
  • BEWARE that you cannot do `next(l)` no more cause de filter object has been "used" some how. – Welgriv Jun 25 '21 at 13:22
33

This is an old question, but I think this question needs an answer using the map-reduce ideology. So here:

from functools import reduce

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

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

This is especially good if n doesn't fit in the computer memory.

quasiyoke
  • 709
  • 9
  • 21
Al Hoo
  • 528
  • 5
  • 11
  • 1
    Is this faster than using len of a list iteration? – Nicolò Gasparini Feb 24 '21 at 10:46
  • 1
    Not with python, but if you want to optimize some algorithm that needs the length of a filtered object, building a list to count the length is not the optimal way. – Al Hoo Feb 25 '21 at 13:37
  • Note that `reduce` was deliberately taken out of the standard library in Python 3.0 and greater. More details about _why_ this was decided can be found here in this thread by Guido van Rossum: https://www.artima.com/weblogs/viewpost.jsp?thread=98196 – Per Lundberg Sep 16 '21 at 07:54
  • It seems that reduce it is going to be here for a while. check: https://docs.python.org/3.13/library/functools.html#functools.reduce – Nicolás Rodríguez Celis Jun 26 '23 at 10:08
19

Converting a filter to a list will take extra memory, which may not be acceptable for large amounts of data. You can find length of the filter object without converting it to a list:

sum(1 for _ in filter(lambda x: x > 3, n))
phoenix
  • 7,988
  • 6
  • 39
  • 45
Mohammad Banisaeid
  • 2,376
  • 27
  • 35
16

Generally, filter and reduce are not pythonic.

@arshajii metioned this solution:

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

This is quite simple, but is not describing what you exactly want to do, and it makes a list that may use some additional memory. A better solution is using sum with generator:

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

(See more about generator here: https://www.python.org/dev/peps/pep-0289/#rationale)

However, sum with generator is actually slower in most cases because of the implementation (tested in 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)
Ian Lin
  • 358
  • 2
  • 7
13

The docs for python 3 say it returns an iterator

"Construct an iterator from those elements of iterable for which function returns true."

In python 2 it returned a list: see here. You will need to iterate the filter object to find its length.

doctorlove
  • 18,872
  • 2
  • 46
  • 62
0

Can be solved using more-itertools:

from more_itertools import ilen
f = filter(lambda x:x>3,n)
return ilen(f)

Note that ilen consumes the filter (you won't be able to use it afterwards - it will return an empty list)

Abra Cadabra
  • 141
  • 6