如何在不使用条件语句的情况下将max和min边界应用于值

use*_*771 5 python

问题:

写一个Python函数,clip(lo,x,hi)如果x小于lo则返回lo; 嗨如果x大于hi; 否则为x.对于这个问题,你可以假设lo <hi.

不要对此问题使用任何条件语句.相反,使用内置的Python函数min和max.在开始此问题之前,您可能希望阅读关于min的文档和max上的文档,并在解释器中稍微使用这些函数.

此函数接收三个数字并返回一个数字.

代码给出:

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
    '''
Run Code Online (Sandbox Code Playgroud)

我的代码已添加:

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
Run Code Online (Sandbox Code Playgroud)

这是问题:我不能使用任何条件.救命!

Nic*_*las 9

这是一个解决方案,假设lo <hi.

def clip(lo, x, hi):
    return max(lo, min(hi, x))
Run Code Online (Sandbox Code Playgroud)

它在每种情况下如何工作:

  • lo,当x <lo:如果lo <hi,那么x <hi,所以min(hi, x)返回xmax(lo, x)返回lo.
  • 嗨,当x> hi:min(hi, x)返回hi并且如果lo <hi,则max(lo, hi)返回hi
  • x,否则:x> lo和x <hi,所以min(hi, x)返回xmax(lo, x)返回x


Pau*_*McG 8

所以到目前为止你有很多选择.尚未发布的是嵌套的三元表达式:

def clip(lo, x, hi):
    return lo if x <= lo else hi if x >= hi else x
Run Code Online (Sandbox Code Playgroud)

但由于这使用了明确的条件测试,可能不适合作为原始问题的解决方案.仍然,给定这些选项,如果x <= lo(所有其他方法评估所有比较和/或执行一个或两个方法调用),这实际上具有短路的优点.让我们看看这些替代方法如何使用timeit实际执行(使用Python 3.3进行测试,因此range不会构建列表,而是返回迭代器):

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
Run Code Online (Sandbox Code Playgroud)

(每次评估2个函数调用,杀死性能)

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
Run Code Online (Sandbox Code Playgroud)

(评估每个评估的测试和构建元组,但至少没有函数调用)

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
Run Code Online (Sandbox Code Playgroud)

(建立元组和排序 - 对不起,Gnibbler,这是最慢的)

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
Run Code Online (Sandbox Code Playgroud)

(最快,没有函数调用,只评估x >= hi是否x > lo)

如果在测试范围内将lo的值移动到更高的值,则可以看到这种短路:

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
Run Code Online (Sandbox Code Playgroud)

(如果要在Python 2.x下重现这些,请替换rangexrange.)