How to apply max & min boundaries to a value without using conditional statements
python
Solution
So you have a number of options proposed so far. Not yet posted is the nested ternary expression:
def clip(lo, x, hi):
return lo if x <= lo else hi if x >= hi else x
But since this uses explicit conditional tests, probably not suitable as a solution to the original question. Still, given these options, this is the one that actually has the advantages of short-circuiting if `x <= lo` (all other methods evaluate all comparisons and/or perform one or two method calls). Let's see how these alternatives actually perform using timeit (tested with Python 3.3, so range does not build a list, but returns an iterator):
python -m timeit -s "lo,hi=10,90" "[max(lo,min(hi,x)) for x in range(100)]"
10000 loops, best of 3: 54.5 usec per loop
(2 function calls per evaluation, kills performance)
python -m timeit -s "lo,hi=10,90" "[(lo,(hi,x)[x<hi])[x>lo] for x in range(100)]"
10000 loops, best of 3: 40.9 usec per loop
(evaluates both tests and builds tuples for every evaluation, but at least no function calls)
python -m timeit -s "lo,hi=10,90" "[sorted((lo,x,hi))[1] for x in range(100)]"
10000 loops, best of 3: 90.5 usec per loop
(builds tuple and sorts - sorry, Gnibbler, this is the slowest)
python -m timeit -s "lo,hi=10,90" "[lo if x <= lo else hi if x >= hi else x for x in range(100)]"
100000 loops, best of 3: 18.9 usec per loop
(fastest, no function calls, only evaluates `x >= hi` if `x > lo`)
This short-circuiting can be seen if you move the value of lo to much higher in the test range:
python -m timeit -s "lo,hi=80,90" "[lo if x <= lo else hi if x >= hi else x for x in range(100)]"
100000 loops, best of 3: 15.1 usec per loop
(If you want to reproduce these under Python 2.x, replace `range` with `xrange`.)
Problem
Problem: Write a Python function, clip(lo, x, hi) that returns lo if x is less than lo; hi if x is greater than hi; and x otherwise. For this problem, you can assume that lo < hi. Don't use any conditional statements for this problem. Instead, use the built in Python functions min and max. You may wish to read the documentation on min and the documentation on max, and play around with these functions a bit in your interpreter, before beginning this problem. This function takes in three numbers and returns a single number. Code Given: ``` def clip(lo, x, hi): ''' Takes in three numbers and returns a value based on the value of x. Returns: - lo, when x < lo - hi, when x > hi - x, otherwise ''' ``` My Code Added: ``` def clip(lo, x, hi): ''' Takes in three numbers and returns a value based on the value of x. Returns: - lo, when x < lo - hi, when x > hi - x, otherwise ''' if min(x, lo, hi) == x: return lo elif max(x, lo, hi) == x: return hi else: return x ``` Here's the problem: I can't use ANY conditionals. Help!