Как найти длину объекта фильтра в 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()

Я не мог получить длину списка, который я получил. Поэтому я попытался сохранить его в переменную, вот так...

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

Вместо использования цикла есть ли способ получить длину этого?


person Srichakradhar    schedule 04.10.2013    source источник
comment
Невозможно узнать, сколько объектов выдаст генератор, прежде чем он их выдаст. Если вы заботитесь об оптимизации, вы можете использовать априорную информацию, чтобы ускорить процесс. Например, если вы знаете, что ваш список отсортирован, вы можете отбросить элементы ниже index(3).   -  person roippi    schedule 04.10.2013


Ответы (5)


Вы должны как-то перебирать объект фильтра. Один из способов - преобразовать его в список:

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

len(l)  # <--

Но это может помешать использованию filter() в первую очередь, поскольку вы могли бы сделать это проще с пониманием списка:

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

Опять же, len(l) вернет длину.

person arshajii    schedule 04.10.2013
comment
Это самый простой способ, но не совсем правильный. Я предпочитаю ответ Аль Ху и цо. Как жаль, что python не поддерживает способ сокращения! - person Ben; 24.09.2017
comment
Это решение требует много дополнительной памяти, если n довольно велико. - person Mohammad Banisaeid; 14.07.2018
comment
ОСТЕРЕГАЙТЕСЬ, что вы больше не можете делать next(l), потому что объект de filter каким-то образом использовался. - person Welgriv; 25.06.2021

Это старый вопрос, но я думаю, что на него нужно ответить, используя идеологию map-reduce. Так вот:

from functools import reduce

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

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

Это особенно хорошо, если n не помещается в памяти компьютера.

person Al Hoo    schedule 04.06.2017
comment
Это быстрее, чем использование len итерации списка? - person Nicolò Gasparini; 24.02.2021
comment
Не с python, но если вы хотите оптимизировать какой-то алгоритм, которому нужна длина отфильтрованного объекта, создание списка для подсчета длины не является оптимальным способом. - person Al Hoo; 25.02.2021

Преобразование фильтра в список потребует дополнительной памяти, что может быть неприемлемо для больших объемов данных. Вы можете найти длину объекта фильтра, не преобразовывая его в список:

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

person Mohammad Banisaeid    schedule 14.07.2018

документы для python 3 говорят, что он возвращает итератор

«Создайте итератор из тех элементов iterable, для которых функция возвращает значение true».

В Python 2 возвращался список: см. здесь. Вам нужно будет перебрать объект фильтра, чтобы найти его длину.

person doctorlove    schedule 04.10.2013

Как правило, filter и reduce не питонические.

@arshajii упомянул это решение:

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

Это довольно просто, но не описывает, что именно вы хотите сделать, и составляет список, который может использовать дополнительную память. Лучшим решением является использование sum с генератором:

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

(Подробнее о генераторе см. здесь: https://www.python.org/dev/peps/pep-0289/#rationale)

Однако sum с генератором на самом деле медленнее в большинстве случаев из-за реализации (проверено в 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)
person Ian Lin    schedule 14.06.2018