7

(使用 Python 3.1)

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

然而,我有一个具体的例子,并希望我可以用它制作干净和 Pythonic 的代码:

#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)

有没有更好的方法来做到这一点?

编辑:对不起愚蠢的符号。函数的参数确实是任意可迭代的,而不是列表。

4

5 回答 5

7
def f(lst):
  flt = filter(lambda x : x is not None and x != 0, lst)
  try:
    return min(flt)
  except ValueError:
    return None

minValueError当序列为空时抛出。这遵循常见的“更容易请求宽恕”范式。

编辑:一个基于 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)
于 2010-10-15T06:36:51.023 回答
2
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

列表推导仅允许不评估为布尔值的项目 false(过滤掉 0 和 None)

一个空列表,即 [] 将评估为 False,因此“if lst:”只会在列表有项目时触发

于 2010-10-15T06:41:33.493 回答
1
t = [1,2,3]
if any(filter(lambda x: x == 10, t)):
   print("found 10")
于 2021-08-10T19:21:45.063 回答
0

你也可以去减少表达return reduce(lambda a,b: a<b and a or b,x) or None

于 2010-10-15T09:41:27.650 回答
0

如果您只想检查过滤器的返回是否为空,您可以这样做(Python3)

len(list(filter(lambda e : e == 2, [1,2,3])))

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

len(list(filter(lambda e : e == 2, [1,2,3]))) len(list(filter(lambda e : e == 2, [1,2,3])))

>>> 1

>>> 1

但:

f = filter(lambda e : e == 2, [1,2,3]) len(list(f)) len(list(f))

>>> 1

>>> 0

于 2020-03-18T15:01:53.233 回答