'How to find the length of a "filter" object in 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()

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?



Solution 1:[1]

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.

Solution 2:[2]

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

Solution 3:[3]

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.

Solution 4:[4]

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)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 quasiyoke
Solution 2 Mohammad Banisaeid
Solution 3
Solution 4