Monday, 15 April 2013

python - How to apply max & min boundaries to a value without using conditional statements -



python - How to apply max & min boundaries to a value without using conditional statements -

problem:

write python function, clip(lo, x, hi) returns lo if x less lo; hi if x greater hi; , x otherwise. problem, can assume lo < hi.

don't utilize conditional statements problem. instead, utilize built in python functions min , max. may wish read documentation on min , documentation on max, , play around these functions bit in interpreter, before origin problem.

this function takes in 3 numbers , returns single number.

code given:

def clip(lo, x, hi): ''' takes in 3 numbers , returns value based on value of x. returns: - lo, when x < lo - hi, when x > hi - x, otherwise '''

my code added:

def clip(lo, x, hi): ''' takes in 3 numbers , returns value based on value of x. returns: - lo, when x < lo - hi, when x > hi - x, otherwise ''' if min(x, lo, hi) == x: homecoming lo elif max(x, lo, hi) == x: homecoming hi else: homecoming x

here's problem: can't utilize any conditionals. help!

so have number of options proposed far. not yet posted nested ternary expression:

def clip(lo, x, hi): homecoming lo if x <= lo else hi if x >= hi else x

but since uses explicit conditional tests, not suitable solution original question. still, given these options, 1 has advantages of short-circuiting if x <= lo (all other methods evaluate comparisons and/or perform 1 or 2 method calls). let's see how these alternatives perform using timeit (tested python 3.3, range not build list, returns iterator):

python -m timeit -s "lo,hi=10,90" "[max(lo,min(hi,x)) 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] x in range(100)]" 10000 loops, best of 3: 40.9 usec per loop

(evaluates both tests , builds tuples every evaluation, @ to the lowest degree no function calls)

python -m timeit -s "lo,hi=10,90" "[sorted((lo,x,hi))[1] x in range(100)]" 10000 loops, best of 3: 90.5 usec per loop

(builds tuple , sorts - sorry, gnibbler, slowest)

python -m timeit -s "lo,hi=10,90" "[lo if x <= lo else hi if x >= hi else x x in range(100)]" 100000 loops, best of 3: 18.9 usec per loop

(fastest, no function calls, evaluates x >= hi if x > lo)

this short-circuiting can seen if move value of lo much higher in test range:

python -m timeit -s "lo,hi=80,90" "[lo if x <= lo else hi if x >= hi else x x in range(100)]" 100000 loops, best of 3: 15.1 usec per loop

(if want reproduce these under python 2.x, replace range xrange.)

python

No comments:

Post a Comment