【问题标题】:How to apply max & min boundaries to a value without using conditional statements如何在不使用条件语句的情况下将最大和最小边界应用于值
【发布时间】:2021-06-03 22:09:50
【问题描述】:

问题:

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

不要对这个问题使用任何条件语句。相反,使用内置的 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
    '''

我的代码已添加:

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

问题出在:我不能使用 ANY 条件。救命!

【问题讨论】:

标签: python


【解决方案1】:

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

def clip(lo, x, hi):
    return max(lo, min(hi, x))

在每种情况下的工作原理:

  • lo,当 x :如果 lo ,则 x min(hi, x) 返回 x 和 max(lo, x) 返回 lo。李>
  • hi,当 x > hi:min(hi, x) 返回 hi 并且 如果 lo ,max(lo, hi) 返回 hi
  • x,否则:x > lo 和 x min(hi, x) 返回x 和max(lo, x) 返回x

【讨论】:

    【解决方案2】:

    到目前为止,您已经提出了许多选项。尚未发布的是嵌套的三元表达式:

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

    但由于这使用显式条件测试,可能不适合作为原始问题的解决方案。尽管如此,考虑到这些选项,如果x &lt;= 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
    

    (每次评估 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
    

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

    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
    

    (构建元组并排序 - 抱歉,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
    

    (最快,无函数调用,仅在 x &gt; lo 时评估 x &gt;= hi)

    如果您将 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
    

    (如果您想在 Python 2.x 下重现这些,请将 range 替换为 xrange。)

    【讨论】:

    • 最好将L=range(100) 放在设置中,因为您没有修改它
    • 有些人可能会说三元表达式是一个条件表达式。
    • 我同意,因此我的评论是“但由于这使用了明确的条件测试,可能不适合作为原始问题的解决方案。”还有一件有趣的事情:我担心将L=range(100) 放入设置中会出现问题,因为我在Python 3.3 中运行,其中range 返回一个迭代器,该迭代器将在第一次测试运行中使用,但随后会以下所有测试运行为空。事实证明并非如此,因此显然在每次测试运行之前都会调用设置代码,只是不包含在时序统计中(或者我可以设置L=list(range(100))。)
    【解决方案3】:

    无需提供整个解决方案 - 您无需“检查”任何内容。从底部开始限制为lo 的值是运行max(x, lo) 得到的值。

    另外,剪裁到一个边界的值不会受到剪裁到另一边界的影响,因此您可以安全地运行一个校正的结果通过另一个校正。

    【讨论】:

      【解决方案4】:

      我翻遍了所有案例,每个案例的答案都是按照大小排列的中间项

              def clip(lo,x,hi):
                   t = hi + lo + x - max(lo,x,hi)- min(lo,x,hi)
                   return t
      

      【讨论】:

        【解决方案5】:

        另一种解决方案:

        def clip(lo, x, hi):
            result = {x: x}
            result[min(x, lo)] = lo
            result[max(x, hi)] = hi
            return result[x]
        

        【讨论】:

          【解决方案6】:

          解决方案:

          def clip(lo, x, hi):
              x = max(lo, x)
              x = min(x, hi)   
              return x
          

          【讨论】:

            【解决方案7】:
            def clip(lo, x, hi):
                return sorted((lo, x, hi))[1]
            

            【讨论】:

            • 聪明但慢 - 看我的时间
            【解决方案8】:

            分钟?最大限度?怎么样:

            def clip(lo,x,hi):
                return (lo,(hi,x)[x<hi])[x>lo]
            

            【讨论】:

              【解决方案9】:

              这将在没有条件运算符的情况下完成。

              max(lo,min(hi,x))
              

              【讨论】:

                【解决方案10】:

                这里还有一个解决方案: 返回 min(max(x, lo), hi)

                【讨论】:

                • 这与 Nicolas 的回答完全相反。这增加了什么?
                猜你喜欢
                • 2013-12-04
                • 1970-01-01
                • 1970-01-01
                • 2016-02-13
                • 1970-01-01
                • 2014-02-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多