Python: min(None, x)
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:
- Worked if None presents in sequence
- Worked on Python 3
- max() will be work also
Cons
- Need more than one non-zero variable in the list. i.e. [0,None] fails.
- 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)
Related videos on Youtube
Comments
-
Jonathan Livni almost 2 years
I would like to perform the following:
a=max(a,3) b=min(b,3)
However sometimes
a
andb
may beNone
.
I was happy to discover that in the case ofmax
it works out nicely, giving my required result3
, however ifb
isNone
,b
remainsNone
...Anyone can think of an elegant little trick to make
min
return the number in case one of the arguments in None?-
Admin almost 13 yearsIt 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
andint
returns a fixed value regardless of the integer value. In Python 3, you get aTypeError
when you do things like that (comparing types that have no meaningful ordering). -
Rafe Kettler almost 13 yearsSeems like an inconsistency in Python, more than anything else.
-
Ben Jackson almost 13 years
-
Shay Tsadok over 4 yearsif 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 almost 13 yearsOkay, then I'll make it a bit more explicit
-
Admin almost 13 yearsNote 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 (and0 == 0.0 == 0j
). -
Pavan Yalamanchili almost 13 yearsThe OP said max was not a problem. Also what happens if b is negative ?
-
Admin almost 13 yearsThen this will pass
True
on occasion ;) -
Admin almost 13 yearsNo need for the list comprehension. Still +1 (in advance - seriously, please remove the brackets), it's a clean and simple solution.
-
utdemir almost 13 yearsThanks, without the braces, does Python interprets it like a generator expression?
-
Admin almost 13 yearsYes. The parens around generator expressions are optional if the genexpr is the sole argument to a function call.
-
Kevin London almost 8 yearsOne 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]
, themin()
function will fail because you're not giving it a valid argument. -
UlrichWuenstel about 6 yearsThis also works for Python 2.7. Since it also resolves the min(None) problem of the other solutions, it gets my +1
-
rrauenza over 4 yearsThis filters out zeros.
-
BazookaDave over 3 yearsA 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 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 over 3 yearsI always try to avoid negations. So I prefer
b = 3 if b is None else min(b, 3)
-
Ron over 3 yearsGreat answer and examples!