У меня такой код:
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()
вместе. Он более компактный, но мне кажется, что он непонятен, труднее найти ошибки, если я напечатаю его неправильно. Другими словами, я не считаю это очень простым.
new_index = max(0, min(new_index, len(mylist)-1))
clamp = lambda value, minv, maxv: max(min(value, maxv), minv)
Использование API из arma.sourceforge.net/docs.html#clampОтветы:
На самом деле это довольно ясно. Многие люди учатся этому быстро. Вы можете использовать комментарий, чтобы помочь им.
new_index = max(0, min(new_index, len(mylist)-1))
источник
def clamp(n, smallest, largest): return max(smallest, min(n, largest))
helperFunctions.py
? Отдельный модуль? Что, если здесь будет множество «вспомогательных функций» для совершенно разных вещей?utils.py
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
источник
sorted()
встроенного. Очень компактный, но немного непонятный. В любом случае, всегда приятно видеть другие креативные решения!min(max())
строительство. Немного быстрее в том случае, если число находится в диапазоне и перестановки не требуются.здесь много интересных ответов, все примерно одинаково, кроме ... какой быстрее?
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, возможно, неудивительно, самая медленная из всех. Вероятно, потому что он ищет массивы, где другие версии просто упорядочивают свои аргументы.
источник
mm_clip
иpy_clip
будет так же быстро, если вы используете JIT-компилятор, например PyPy. За исключением того, что первое более читабельно, а читаемость в философии Python более важна, чем небольшое повышение производительности в большинстве случаев.См. Numpy.clip :
index = numpy.clip(index, 0, len(my_list) - 1)
источник
clip
являетсяa
«массив, содержащий элементы для обрезки». Так что писать придетсяnumpy.clip([index], …
, а неnumpy.clip(index, …
.Цепочка
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])
источник
min
иmax
это намного понятнее, чем связка условных выражений. (Я не знаю, для чегоadd
- просто скажитеclamp(val + 7, 0, 42)
.)Мне этот кажется более питоническим:
>>> 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
источник
Если ваш код кажется слишком громоздким, может помочь функция:
def clamp(minvalue, value, maxvalue): return max(minvalue, min(value, maxvalue)) new_index = clamp(0, new_index, len(mylist)-1)
источник
Избегайте написания функций для таких небольших задач, если вы не применяете их часто, поскольку это загромождает ваш код.
для отдельных значений:
для списков значений:
map(lambda x: min(clamp_max, max(clamp_min, x)), values)
источник