Python: min(None, x)

27,750

Solution 1

Why don't you just create a generator without None values? It's simplier and cleaner.

>>> l=[None ,3]
>>> min(i for i in l if i is not None)
3

Solution 2

A solution for the Python 3

Code:

# variable lst is your sequence

min(filter(lambda x: x is not None, lst)) if any(lst) else None

Examples:

In [3]: lst = [None, 1, None]

In [4]: min(filter(lambda x: x is not None, lst)) if any(lst) else None
Out[4]: 1

In [5]: lst = [-4, None, 11]

In [6]: min(filter(lambda x: x is not None, lst)) if any(lst) else None
Out[6]: -4

In [7]: lst = [0, 7, -79]

In [8]: min(filter(lambda x: x is not None, lst)) if any(lst) else None
Out[8]: -79

In [9]: lst = [None, None, None]

In [10]: min(filter(lambda x: x is not None, lst)) if any(lst) else None

In [11]: print(min(filter(lambda x: x is not None, lst)) if any(lst) else None)
None

Notes:

Worked in sequence presents as numbers as well as None. If all values is None min() raise exception

ValueError: min() arg is an empty sequence

This code resolve this problem at all

Pros:

  1. Worked if None presents in sequence
  2. Worked on Python 3
  3. max() will be work also

Cons

  1. Need more than one non-zero variable in the list. i.e. [0,None] fails.
  2. Need a variable (example lst) or need duplicate the sequence

Solution 3

My solution for Python 3 (3.4 and greater):

min((x for x in lst if x is not None), default=None)
max((x for x in lst if x is not None), default=None)

Solution 4

Here is an inline decorator that you can use to filter out None values that might be passed to a function:

noNones = lambda fn : lambda *args : fn(a for a in args if a is not None)
print noNones(min)(None, 3)
print noNones(max)(None, 3)

prints:

3
3

Solution 5

def max_none(a, b):
    if a is None:
        a = float('-inf')
    if b is None:
        b = float('-inf')
    return max(a, b)

def min_none(a, b):
    if a is None:
        a = float('inf')
    if b is None:
        b = float('inf')
    return min(a, b)

max_none(None, 3)
max_none(3, None)
min_none(None, 3)
min_none(3, None)
Share:
27,750

Related videos on Youtube

Jonathan Livni
Author by

Jonathan Livni

python, django, C++ and other vegetables...

Updated on July 09, 2022

Comments

  • Jonathan Livni
    Jonathan Livni almost 2 years

    I would like to perform the following:

    a=max(a,3)
    b=min(b,3)
    

    However sometimes a and b may be None.
    I was happy to discover that in the case of max it works out nicely, giving my required result 3, however if b is None, b remains None...

    Anyone can think of an elegant little trick to make min return the number in case one of the arguments in None?

    • Admin
      Admin almost 13 years
      It doesn't do the right thing. It happens to give the result you expect in one of two cases because the nonsensical comparision between NoneType and int returns a fixed value regardless of the integer value. In Python 3, you get a TypeError when you do things like that (comparing types that have no meaningful ordering).
    • Rafe Kettler
      Rafe Kettler almost 13 years
      Seems like an inconsistency in Python, more than anything else.
    • Ben Jackson
      Ben Jackson almost 13 years
    • Shay Tsadok
      Shay Tsadok over 4 years
      if you are ok with replacing None to a default int value (like 0), you can do something like this: max(a,3,key=lambda x: x or 0)
  • Blender
    Blender almost 13 years
    Okay, then I'll make it a bit more explicit
  • Admin
    Admin almost 13 years
    Note that this only works if the default is 0. Passing 0 instead of None still triggers passing the default but doesn't change the value since the default is 0 (and 0 == 0.0 == 0j).
  • Pavan Yalamanchili
    Pavan Yalamanchili almost 13 years
    The OP said max was not a problem. Also what happens if b is negative ?
  • Admin
    Admin almost 13 years
    Then this will pass True on occasion ;)
  • Admin
    Admin almost 13 years
    No need for the list comprehension. Still +1 (in advance - seriously, please remove the brackets), it's a clean and simple solution.
  • utdemir
    utdemir almost 13 years
    Thanks, without the braces, does Python interprets it like a generator expression?
  • Admin
    Admin almost 13 years
    Yes. The parens around generator expressions are optional if the genexpr is the sole argument to a function call.
  • Kevin London
    Kevin London almost 8 years
    One potential problem with a solution like this is that it works fine for the listed example but if you have a list with [None, None], the min() function will fail because you're not giving it a valid argument.
  • UlrichWuenstel
    UlrichWuenstel about 6 years
    This also works for Python 2.7. Since it also resolves the min(None) problem of the other solutions, it gets my +1
  • rrauenza
    rrauenza over 4 years
    This filters out zeros.
  • BazookaDave
    BazookaDave over 3 years
    A boundary case that this does not handle is if it is possible for lst to contain only 0 and None values. You would want it to return 0, but it will return None.
  • rahul.deshmukhpatil
    rahul.deshmukhpatil over 3 years
    @KevinLondon, specify the default value for the min as 0 or None depending upon the behavior you want. min((x for x in [None,None] if x is not None), default=None)
  • Martin Thoma
    Martin Thoma over 3 years
    I always try to avoid negations. So I prefer b = 3 if b is None else min(b, 3)
  • Ron
    Ron over 3 years
    Great answer and examples!