Как посчитать ненулевые элементы в итерируемом? - PullRequest
13 голосов
/ 03 августа 2010

Я ищу лучшее / более Pythonic решение для следующего фрагмента

count = sum(1 for e in iterable if e)

Ответы [ 9 ]

21 голосов
/ 03 августа 2010
len(filter(None, iterable))

Использование None в качестве предиката для filter просто говорит об истинности предметов. (может быть, яснее будет len(filter(bool, iterable)))

4 голосов
/ 03 августа 2010

Честно говоря, я не могу придумать лучшего способа сделать это, чем у вас есть.

Ну, я думаю, что люди могли бы поспорить о "лучше", но я думаю, что вы вряд ли найдете что-то более короткое, простое и понятное.

3 голосов
/ 03 августа 2010

Большинство Pythonic - это написать небольшую вспомогательную функцию и поместить ее в ваш надежный модуль «утилит» (или подмодуль соответствующего пакета, когда вам достаточно; -):

import itertools as it

def count(iterable):
  """Return number of items in iterable."""
  return sum(1 for _ in iterable)

def count_conditional(iterable, predicate=None):
  """Return number of items in iterable that satisfy the predicate."""
  return count(it.ifilter(predicate, iterable))

Точно то, как вы решите реализовать эти утилиты, менее важно (вы можете в любой момент перекодировать некоторые из них в Cython, например, если какое-то профилирование приложения с использованием утилит показывает, что это полезно ): главное, чтобы они были вашей собственной полезной библиотекой служебных функций с именами и шаблонами вызовов , которые вам нравятся, чтобы сделать ваш важный прикладной уровень более понятным и читаемым кодом , и более кратко, что если вы наполнили его полным встроенными искажениями! -)

2 голосов
/ 03 августа 2010
sum(not not e for e in iterable)
0 голосов
/ 19 июля 2018

Как указано в комментариях, название несколько противоречит вопросу. Если бы мы настаивали на названии, то есть подсчете ненулевых элементов, решение ОП могло бы быть изменено на:

count = sum(1 for e in iterable if e is not None)
0 голосов
/ 09 марта 2012

Вот решение с O (n) временем выполнения и O (1) дополнительной памятью:

count = reduce(lambda x,y:x+y, imap(lambda v: v>0, iterable))

Надеюсь, это поможет!

0 голосов
/ 03 августа 2010

Вероятно, самый Pythonic способ - это написать код, который не нуждается в функции подсчета.

Обычно быстрее всего написать стиль функций, который вам лучше всего подходит, и продолжить совершенствовать свой стиль.

Записывайте один раз, часто читайте код.

Кстати, ваш код не выполняет то, что говорит ваш заголовок!Считать не 0 элементов непросто, учитывая ошибки округления в плавающих числах, что False равно 0 ..

Если у вас нет значений с плавающей запятой в списке, это может сделать это:

def nonzero(seq):
  return (item for item in seq if item!=0) 

seq = [None,'', 0, 'a', 3,[0], False] 
print seq,'has',len(list(nonzero(seq))),'non-zeroes' 

print 'Filter result',len(filter(None, seq))

"""Output:
[None, '', 0, 'a', 3, [0], False] has 5 non-zeroes
Filter result 3
"""
0 голосов
/ 03 августа 2010

Если вы просто пытаетесь увидеть, не является ли итерация пустой, то это, вероятно, поможет:

def is_iterable_empty(it):
    try:
        iter(it).next()
    except StopIteration:
        return True
    else:
        return False

Другие ответы займут O (N) время для завершения (а некоторые - O(N) память; хороший глаз, Джон!).Эта функция занимает O (1) раз.Если вам действительно нужна длина, то другие ответы помогут вам больше.

0 голосов
/ 03 августа 2010

Это не самый быстрый, но, возможно, удобный код-гольф

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