Как зажать целое число в некотором диапазоне?
у меня есть следующий код:
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 строки. Это довольно многословно, немного некрасиво... Осмелюсь сказать, это довольно ООН-подходящие для Python.
есть ли другое более простое и компактное решение? (и больше весть)
Да, я знаю, что могу использовать if else
в одной строке, но это не читается:
new_index = 0 if new_index < 0 else len(mylist) - 1 if new_index >= len(mylist) else new_index
Я также знаю, что я могу цепи max()
и min()
вместе. Он более компактный, но я чувствую, что это немного неясно, сложнее найти ошибки, если я наберу его неправильно. Другими словами, Я не нахожу это очень простым.
new_index = max(0, min(new_index, len(mylist)-1))
9 ответов:
Это понятно, на самом деле. Многие люди быстро учатся этому. Вы можете использовать комментарий, чтобы помочь им.
new_index = max(0, min(new_index, len(mylist)-1))
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
посмотреть numpy.клип:
index = numpy.clip(index, 0, len(my_list) - 1)
много интересных ответов здесь, все о том же, за исключением... кто быстрее?
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
paxdiablo есть!, используйте простой старый питон. Версия numpy, возможно, не удивительно, самая медленная из всех. Вероятно, потому что он ищет массивы, где другие версии просто упорядочивают свои аргументы.
сцепление
max()
иmin()
вместе-это нормальная идиома, которую я видел. Если вам трудно читать, напишите вспомогательную функцию для инкапсуляции операции:def clamp(minimum, x, maximum): return max(minimum, min(x, maximum))
что случилось с моим любимым читаемым языком 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)
если бы вы хотели, вы могли бы даже сделать список min / max, чтобы он выглядел более "математически чистым":
x = restrict (val+7, [0, 42])
Если ваш код кажется слишком громоздким, функция может помочь:
def clamp(minvalue, value, maxvalue): return max(minvalue, min(value, maxvalue)) new_index = clamp(0, new_index, len(mylist)-1)