Python过滤器/max组合-检查空迭代器

Python过滤器/max组合-检查空迭代器,python,filter,iterator,python-3.x,iterable,Python,Filter,Iterator,Python 3.x,Iterable,(使用Python 3.1) 我知道,对于测试迭代器是否为空的一般问题,这个问题已经被问过很多次了;显然,没有一个简洁的解决方案(我想这是有原因的——迭代器在被要求返回下一个值之前并不知道它是否为空) 然而,我有一个具体的例子,我希望我能用它编写出清晰的Python代码: #lst is an arbitrary iterable #f must return the smallest non-zero element, or return None if empty def f(lst):

(使用Python 3.1)

我知道,对于测试迭代器是否为空的一般问题,这个问题已经被问过很多次了;显然,没有一个简洁的解决方案(我想这是有原因的——迭代器在被要求返回下一个值之前并不知道它是否为空)

然而,我有一个具体的例子,我希望我能用它编写出清晰的Python代码:

#lst is an arbitrary iterable
#f must return the smallest non-zero element, or return None if empty
def f(lst):
  flt = filter(lambda x : x is not None and x != 0, lst)
  if # somehow check that flt is empty
    return None
  return min(flt)
有没有更好的办法

编辑:为愚蠢的符号道歉。函数的参数实际上是一个任意的iterable,而不是一个列表

def f(lst):
  flt = filter(lambda x : x is not None and x != 0, lst)
  try:
    return min(flt)
  except ValueError:
    return None
当序列为空时,
min
抛出
ValueError
。这遵循了常见的“更容易请求原谅”范式

编辑:基于reduce的解决方案,无例外

from functools import reduce
def f(lst):
  flt = filter(lambda x : x is not None and x != 0, lst)
  m = next(flt, None)
  if m is None:
    return None
  return reduce(min, flt, m)
列表理解只允许不计算布尔值的项为false(过滤掉0和None)


空列表,即[]将计算为False,因此“if lst:”将仅在列表包含项时触发

您也可以使用reduce表达式
返回reduce(lambda,b:a如果您只想检查过滤器的返回是否为空,您可以这样做(Python3)

len(列表(过滤器(λe:e==2[1,2,3]))

但请注意,过滤器是一个生成器,如果您进行两次此测试,第二次,您将收到不同的结果:

len(列表(过滤器(λe:e==2[1,2,3]))
len(列表(过滤器(λe:e==2[1,2,3]))

>>>一,

>>>一,

但是:

f=filter(λe:e==2[1,2,3])
len(名单(f))
len(列表(f))

>>>一,


>>>0

Yes.activestatepython3.1.2.
itertools.c_c_c_c_c_组合_BREAKER()
我担心
ValueError
不是由空列表引起的。是否100%确定min在任何其他情况下都不会引起
ValueError
?此外,我可能需要用列表理解替换
lst
;在这种情况下,我甚至更担心由我自己的代码在列表理解中。@max,我不是肯定的,因为Python在记录这类事情方面不是很好。然而,
flt
应该总是可以使用的。即使它不是,如果你传递了错误类型的参数,它看起来像
min
抛出
TypeError
。我想不出任何其他
min
本身会抛出。现在,它看起来像是一个列表。如果不是,它肯定是一个误导性的名称。在这种情况下,你不必担心列表理解,因为它在
f
开始之前就已经完全完成了。如果它是生成器理解,那就有点复杂了。感觉有点复杂如果Python不记录这种类型的东西,那就很危险。毕竟,我正在为载人定居者乘坐的宇宙飞船上的生命支持模块编写软件……啊,没关系:)但我不喜欢依赖内置的特定异常类型,除非它有大量的文档记录。如果我把它列出来,我想最好明确地检查它的长度。@max,我发布了一个解决方案,可以避免列表和异常。如果需要,可以用一个更严格的集合替换“if item”,这很简单,但是我不认为“”[]、set()、tuple()算作非零;)看起来他在用他的min()调用寻找数字。这并没有回答OP的问题,这仍然存在空迭代器或空列表的问题。转换为列表只是为了查看迭代器是否为空既低效又冗长。
def f(lst):
    # if you want the exact same filtering as the original, you could use
    # lst = [item for item in lst if (item is not None and item != 0)]

    lst = [item for item in lst if item]
    if lst: return min(lst)
    else: return None