'Python: min(None, x)
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?
Solution 1:[1]
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 2:[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:[3]
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 4:[4]
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)
Solution 5:[5]
You can use an inline if and an infinity as the default, as that will work for any value:
a = max(a if a is not None else float('-inf'), 3)
b = min(b if b is not None else float('inf'), 3)
Solution 6:[6]
a=max(a,3) if a is not None else 3
b=min(b,3) if b is not None else 3
Solution 7:[7]
@utdemir's answer works great for the provided example but would raise an error in some scenarios.
One issue that comes up is if you have a list with only None values. If you provide an empty sequence to min(), it will raise an error:
>>> mylist = [None, None]
>>> min(value for value in mylist if value)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence
As such, this snippet would prevent the error:
def find_minimum(minimums):
potential_mins = (value for value in minimums if value is not None)
if potential_mins:
return min(potential_mins)
Solution 8:[8]
I believe the cleanest way is to use filter built-in function
a = max(filter(None, [a, 3]))
b = min(filter(None, [b, 3]))
Solution 9:[9]
If you can use np.nan instead of None:
import numpy as np
float(np.nanmax([a, np.nan]))
float(np.nanmin([a, np.nan]))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | R1tschY |
| Solution 2 | André Guerra |
| Solution 3 | PaulMcG |
| Solution 4 | |
| Solution 5 | |
| Solution 6 | |
| Solution 7 | |
| Solution 8 | Sam |
| Solution 9 | alEx |
