119

次のコードがあります。

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 行に分けて記述する必要がありました。それは非常に冗長で、少し醜いです...あえて言うと、それはかなり非 pythonicです。

他のよりシンプルでコンパクトなソリューションはありますか? (そしてよりpythonic

はい、if else1行で使用できることはわかっていますが、判読できません:

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

9 に答える 9

148

これは実際にはかなり明確です。多くの人はすぐに習得します。コメントを使用してそれらを支援できます。

new_index = max(0, min(new_index, len(mylist)-1))
于 2010-11-03T23:21:03.310 に答える
110
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
于 2010-11-03T23:43:50.477 に答える
55

ここには多くの興味深い答えがありますが、すべてほぼ同じですが...どちらが速いですか?

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はそれを持っています!、普通の python を使用してください。numpy バ​​ージョンは、おそらく驚くべきことではないが、最も遅いバージョンです。おそらく、他のバージョンが引数を順序付けるだけの配列を探しているためです。

于 2014-04-07T03:05:47.350 に答える
40

numpy.clipを参照してください:

index = numpy.clip(index, 0, len(my_list) - 1)
于 2011-05-16T06:28:49.600 に答える
24

Chaining max()and min()together は、私が見た通常のイディオムです。読みにくい場合は、操作をカプセル化するヘルパー関数を記述します。

def clamp(minimum, x, maximum):
    return max(minimum, min(x, maximum))
于 2010-11-03T23:25:32.817 に答える
23

私の最愛の読みやすい 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])
于 2010-11-03T23:23:38.690 に答える
18

これは私にはよりpythonicに思えます:

>>> 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
于 2016-05-02T19:09:56.183 に答える
12

コードが扱いにくいと思われる場合は、次の関数が役立ちます。

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

new_index = clamp(0, new_index, len(mylist)-1)
于 2010-11-03T23:22:25.663 に答える
0

コードが乱雑になるため、頻繁に適用する場合を除き、このような小さなタスク用の関数を作成しないでください。

個々の値について:

min(clamp_max, max(clamp_min, value))

値のリストの場合:

map(lambda x: min(clamp_max, max(clamp_min, x)), values)
于 2011-10-04T10:05:08.067 に答える