Python Filter / Max Combo - Checking for Empty Iterator

Python Filter / Max Combo - Checking for Empty Iterator

(Using Python 3.1)

I know this question has been asked many times for the general question of testing if iterator is empty; obviously, there's no neat solution to that (I guess for a reason - an iterator doesn't really know if it's empty until it's asked to return its next value).

I have a specific example, however, and was hoping I can make clean and Pythonic code out of it:

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

Is there any better way to do that?

EDIT: sorry for the stupid notation. The parameter to the function is indeed an arbitrary iterable, rather than a list.

2

5 Answers

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

min throws ValueError when the sequence is empty. This follows the common "Easier to Ask for Forgiveness" paradigm.

EDIT: A reduce-based solution without exceptions

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)
9
t = [1,2,3]
if any(filter(lambda x: x == 10, t)):
   print("found 10")
1
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

the list comprehension only allows items that don't evaluate to boolean false (which filters out 0 and None)

an empty list i.e. [] will evaluate to False, so "if lst:" will only trigger if the list has items

1

you can go for reduce expression too return reduce(lambda a,b: a<b and a or b,x) or None

1

If you just want to check if the return of filter is empty, you might do (Python3)

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

But notice, hence filter is a generator if you this test twice, second time, you will receive a diferent result:

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

>>> 1

>>> 1

But:

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

>>> 1

>>> 0

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Robert Thorne
Author

Robert Thorne

Robert Thorne covers electric vehicle innovations, autonomous driving systems, global mobility trends, and automotive engineering developments.