简体   繁体   English

如何计算可迭代中的非null元素?

[英]How to count non-null elements in an iterable?

我正在为以下代码片段寻找更好/更多的Pythonic解决方案

count = sum(1 for e in iterable if e)
len(filter(None, iterable))

Using None as the predicate for filter just says to use the truthiness of the items. 使用None作为filter的谓词只是说使用项目的真实性。 (maybe clearer would be len(filter(bool, iterable)) ) (可能更清楚的是len(filter(bool, iterable))

Honestly, I can't think of a better way to do it than what you've got. 老实说,我想不出比你所拥有的更好的方法。

Well, I guess people could argue about "better," but I think you're unlikely to find anything shorter, simpler, and clearer. 好吧,我想人们可以争论“更好”,但我认为你不太可能找到更短,更简单,更清晰的东西。

Most Pythonic is to write a small auxiliary function and put it in your trusty "utilities" module (or submodule of appropriate package, when you have enough;-): 大多数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))

Exactly how you choose to implement these utilities is less important (you could choose at any time to recode some of them in Cython, for example, if some profiling on an application using the utilities shows it's useful): the key thing is having them as your own useful library of utility functions, with names and calling patterns you like, to make your all-important application level code clearer, more readable, and more concise that if you stuffed it full of inlined contortions!-) 确切地说, 如何选择实现这些实用程序并不重要(您可以随时选择在Cython中重新编写其中一些实用程序,例如,如果使用实用程序对应用程序进行一些分析显示它很有用):关键是将它们作为你自己有用的实用函数库, 喜欢的名字和调用模式,使你的所有重要的应用程序级代码更清晰,更易读,更简洁,如果你把它充满了内联的扭曲! - )

sum(not not e for e in iterable)

As stated in the comments, the title is somewhat dissonant with the question. 正如评论中所述,标题与这个问题有点不协调。 If we would insist on the title, ie counting non-null elements, the OP's solution could be modified to: 如果我们坚持标题,即计算非空元素,OP的解决方案可以修改为:

count = sum(1 for e in iterable if e is not None)

这不是最快的,但对于代码高尔夫来说可能很方便

sum(map(bool, iterable))

If you're just trying to see whether the iterable is not empty, then this would probably help: 如果你只是想看看iterable是否为空,那么这可能会有所帮助:

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

The other answers will take O(N) time to complete (and some take O(N) memory; good eye, John!). 其他答案将花费O(N)时间来完成(有些人需要O(N)记忆;好眼睛,约翰!)。 This function takes O(1) time. 此功能需要O(1)时间。 If you really need the length, then the other answers will help you more. 如果你真的需要长度,那么其他答案将帮助你更多。

Propably the most Pythonic way is to write code that does not need count function. 可比的Pythonic方法是编写不需要count函数的代码。

Usually fastest is to write the style of functions that you are best with and continue to refine your style. 通常最快的是编写您最喜欢的功能样式并继续改进您的风格。

Write Once Read Often code. 一次写入常常编写代码。

By the way your code does not do what your title says! 顺便说一句,你的代码没有做你的标题所说的! To count not 0 elements is not simple considering rounding errors in floating numbers, that False is 0.. 考虑到浮点数中的舍入误差,计算非0元素并不简单,False为0。

If you have not floating point values in list, this could do it: 如果列表中没有浮点值,则可以执行以下操作:

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

Here is a solution with O(n) runtime and O(1) additional memory: 这是一个具有O(n)运行时和O(1)附加内存的解决方案:

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

Hope that helps! 希望有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM