如何将整数限制在某个范围内?

我有以下密码:

new_index = index + offset
if new_index < 0:
new_index = 0
if new_index >= len(mylist):
new_index = len(mylist) - 1
return mylist[new_index]

基本上,我计算一个新索引并使用它从列表中查找一些元素。为了确保索引在列表的边界内,我需要将这2个 if语句分成4行。这是相当冗长,有点丑... 我敢说,这是相当 非蟒蛇

还有其他更简单、更紧凑的解决方案吗? (和更多的 蟒蛇)

是的,我知道我可以在一行中使用 if else,但它是不可读的:

new_index = 0 if new_index < 0 else len(mylist) - 1 if new_index >= len(mylist) else new_index

我也知道我可以把 max()min()连在一起。它更紧凑,但我觉得它有点模糊,如果我输错了,就更难找到 bug。换句话说,我不觉得这很简单。

new_index = max(0, min(new_index, len(mylist)-1))
162856 次浏览

事实上,这一点非常清楚。许多人学得很快。你可以用评论来帮助他们。

new_index = max(0, min(new_index, len(mylist)-1))

如果您的代码看起来太笨拙,那么一个函数可能会有所帮助:

def clamp(minvalue, value, maxvalue):
return max(minvalue, min(value, maxvalue))


new_index = clamp(0, new_index, len(mylist)-1)

我喜爱的可读 Python 语言怎么了? : -)

说真的,把它变成一个函数:

def addInRange(val, add, minval, maxval):
newval = val + add
if newval < minval: return minval
if newval > maxval: return maxval
return newval

那就这么说吧:

val = addInRange(val, 7, 0, 42)

或者一个更简单、更灵活的解决方案,你自己来计算:

def restrict(val, minval, maxval):
if val < minval: return minval
if val > maxval: return maxval
return val


x = restrict(x+10, 0, 42)

如果你愿意,你甚至可以把最小/最大值作为一个列表,这样它看起来更“数学上的纯粹”:

x = restrict(val+7, [0, 42])

max()min()连接在一起是我见过的常见习语。如果您觉得难以阅读,那么编写一个 helper 函数来封装该操作:

def clamp(minimum, x, maximum):
return max(minimum, min(x, maximum))
sorted((minval, value, maxval))[1]

例如:

>>> minval=3
>>> maxval=7
>>> for value in range(10):
...   print sorted((minval, value, maxval))[1]
...
3
3
3
3
4
5
6
7
7
7

笨蛋,剪辑:

index = numpy.clip(index, 0, len(my_list) - 1)

避免为这样的小任务编写函数,除非经常应用它们,因为它们会使代码杂乱无章。

个人价值观:

min(clamp_max, max(clamp_min, value))

价值观列表:

map(lambda x: min(clamp_max, max(clamp_min, x)), values)

这里有很多有趣的答案,都差不多,除了... 哪个更快?

import numpy
np_clip = numpy.clip
mm_clip = lambda x, l, u: max(l, min(u, x))
s_clip = lambda x, l, u: sorted((x, l, u))[1]
py_clip = lambda x, l, u: l if x < l else u if x > u else x
>>> import random
>>> rrange = random.randrange
>>> %timeit mm_clip(rrange(100), 10, 90)
1000000 loops, best of 3: 1.02 µs per loop


>>> %timeit s_clip(rrange(100), 10, 90)
1000000 loops, best of 3: 1.21 µs per loop


>>> %timeit np_clip(rrange(100), 10, 90)
100000 loops, best of 3: 6.12 µs per loop


>>> %timeit py_clip(rrange(100), 10, 90)
1000000 loops, best of 3: 783 ns per loop

帕克斯达布洛拿到了!使用普通的 ol’python。麻木的版本,也许不足为奇,是最慢的。可能是因为它在寻找数组,其他版本的数组只是对参数进行排序。

这个对我来说更像蟒蛇:

>>> def clip(val, min_, max_):
...     return min_ if val < min_ else max_ if val > max_ else val

一些测试:

>>> clip(5, 2, 7)
5
>>> clip(1, 2, 7)
2
>>> clip(8, 2, 7)
7