Подсчет положительных целочисленных элементов в списке с Python перечисляет понимания

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

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

Это походит на достойное понимание, но мне действительно не нравится "1"; это походит на что-то вроде магического числа. Существует ли больше Pythonish способ сделать это?

46
задан smci 17 November 2017 в 19:50
поделиться

5 ответов

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

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

Помните, что результаты timeit могут отличаться в зависимости от версии 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.

77
ответ дан 26 November 2019 в 20:13
поделиться

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

уменьшить (лямбда x, y: x + 1, если y> 0, иначе x, частоты)

РЕДАКТИРОВАТЬ: Вдохновленный принятым ответом от @ ~ unutbu:

уменьшить (лямбда x, y: x + (y> 0), частоты)

1
ответ дан 26 November 2019 в 20:13
поделиться

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

sum(k>0 for k in x)
4
ответ дан 26 November 2019 в 20:13
поделиться

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

len([x for x in frequencies if x > 0])
9
ответ дан 26 November 2019 в 20:13
поделиться

Немного более питоническим способом было бы использовать вместо него генератор:

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

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

24
ответ дан 26 November 2019 в 20:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: