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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4092528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 14:11:53  来源:igfitidea点击:

How to clamp an integer to some range?

pythonclamp

提问by Denilson Sá Maia

I have the following code:

我有以下代码:

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]

Basically, I calculate a new index and use that to find some element from a list. In order to make sure the index is inside the bounds of the list, I needed to write those 2 ifstatements spread into 4 lines. That's quite verbose, a bit ugly... Dare I say, it's quite un-pythonic.

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

Is there any other simpler and more compact solution?(and more pythonic)

还有其他更简单、更紧凑的解决方案吗?(以及更多Pythonic

Yes, i know I can use if elsein one line, but it is not readable:

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

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

I also know I can chain max()and min()together. It's more compact, but I feel it's kinda obscure, more difficult to find bugs if I type it wrong. In other words, I don't find it very straightforward.

我也知道我可以链max()min()在一起。它更紧凑,但我觉得它有点晦涩,如果我输入错误更难找到错误。换句话说,我觉得它不是很简单。

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

采纳答案by S.Lott

This is pretty clear, actually. Many folks learn it quickly. You can use a comment to help them.

这其实很清楚。许多人很快就学会了。您可以使用评论来帮助他们。

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

回答by Greg Hewgill

If your code seems too unwieldy, a function might help:

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

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

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

回答by paxdiablo

Whatever happened to my beloved readable Python language? :-)

我心爱的可读 Python 语言发生了什么事?:-)

Seriously, just make it a function:

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

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

then just call it with something like:

然后只需使用以下内容调用它:

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

Or a simpler, more flexible, solution where you do the calculation yourself:

或者您自己进行计算的更简单、更灵活的解决方案:

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

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

If you wanted to, you could even make the min/max a list so it looks more "mathematically pure":

如果您愿意,您甚至可以将 min/max 列成一个列表,使其看起来更“数学上纯”:

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

回答by Laurence Gonsalves

Chaining max()and min()together is the normal idiom I've seen. If you find it hard to read, write a helper function to encapsulate the operation:

链接max()min()在一起是我见过的正常习语。如果觉得难读,可以写一个辅助函数来封装操作:

def clamp(minimum, x, maximum):
    return max(minimum, min(x, maximum))

回答by John La Rooy

sorted((minval, value, maxval))[1]

for example:

例如:

>>> 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

回答by Neil G

See numpy.clip:

numpy.clip

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

回答by Jetze Schaafsma

Avoid writing functions for such small tasks, unless you apply them often, as it will clutter up your code.

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

for individual values:

对于个人价值:

min(clamp_max, max(clamp_min, value))

for lists of values:

对于值列表:

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

回答by SingleNegationElimination

many interesting answers here, all about the same, except... which one's faster?

这里有很多有趣的答案,大体相同,除了……哪个更快?

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

paxdiablohas it!, use plain ol' python. The numpy version is, perhaps not surprisingly, the slowest of the lot. Probably because it's looking for arrays, where the other versions just order their arguments.

paxdiablo有它!,使用普通的 ol' python。numpy 版本可能是最慢的,这并不奇怪。可能是因为它正在寻找数组,而其他版本只是对它们的参数进行排序。

回答by Jens

This one seems more pythonic to me:

这个对我来说似乎更像pythonic:

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

A few tests:

几个测试:

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