Подсчет положительных целочисленных элементов в списке с использованием списков Python - PullRequest
43 голосов
/ 25 мая 2010

У меня есть список целых чисел, и мне нужно посчитать, сколько из них> 0.
В настоящее время я делаю это со списком, который выглядит следующим образом:

sum([1 for x in frequencies if x > 0])

Это похоже на приличное понимание, но мне не очень нравится "1"; это похоже на магическое число. Есть ли более Pythonish способ сделать это?

Ответы [ 6 ]

76 голосов
/ 25 мая 2010

Если вы хотите уменьшить объем памяти, вы можете избежать создания временного списка с помощью генератора:

sum(x > 0 for x in frequencies)

Это работает, потому что bool является подклассом int:

>>> isinstance(True,int)
True
Значение

и True равно 1:

>>> True==1
True

Однако, как отмечает Джо Голтон в комментариях, это решение не очень быстрое. Если у вас достаточно памяти для использования промежуточного временного списка, то решение sth может быть быстрее. Вот некоторые моменты, сравнивающие различные решения:

>>> frequencies = [random.randint(0,2) for i in range(10**5)]

>>> %timeit len([x for x in frequencies if x > 0])   # sth
100 loops, best of 3: 3.93 ms per loop

>>> %timeit sum([1 for x in frequencies if x > 0])
100 loops, best of 3: 4.45 ms per loop

>>> %timeit sum(1 for x in frequencies if x > 0)
100 loops, best of 3: 6.17 ms per loop

>>> %timeit sum(x > 0 for x in frequencies)
100 loops, best of 3: 8.57 ms per loop

Помните, что результаты могут меняться в зависимости от версии Python, ОС или аппаратного обеспечения.

Конечно, если вы занимаетесь математикой для большого списка чисел, вам, вероятно, следует использовать NumPy:

>>> frequencies = np.random.randint(3, size=10**5)
>>> %timeit (frequencies > 0).sum()
1000 loops, best of 3: 669 us per loop

Массив NumPy требует меньше памяти, чем эквивалентный список Python, и вычисление может быть выполнено намного быстрее, чем любое чистое решение Python.

23 голосов
/ 25 мая 2010

Немного более Pythonic способ будет использовать генератор вместо:

sum(1 for x in frequencies if x > 0)

Это позволяет избежать генерации всего списка перед вызовом sum().

9 голосов
/ 25 мая 2010

Вы можете использовать len() в отфильтрованном списке:

len([x for x in frequencies if x > 0])
4 голосов
/ 25 мая 2010

Это работает, но добавление bool s в качестве int s может быть опасным. Пожалуйста, возьмите этот код с крошкой соли (ремонтопригодность идет в первую очередь):

sum(k>0 for k in x)
1 голос
/ 21 августа 2011

Если массив содержит только элементы> = 0 (т.е. все элементы либо 0, либо положительное целое число), то вы можете просто посчитать нули и вычесть это число из длины массива:

len(arr) - arr.count(0)
0 голосов
/ 25 мая 2010

Как насчет этого?

reduce(lambda x, y: x+1 if y > 0 else x, frequencies)

EDIT: С вдохновением от принятого ответа от @ ~ unutbu:

reduce(lambda x, y: x + (y > 0), frequencies)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...