Saya memiliki kode berikut:
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]
Pada dasarnya, saya menghitung indeks baru dan menggunakannya untuk menemukan beberapa elemen dari daftar. Untuk memastikan indeks berada di dalam batas-batas daftar, saya perlu menulis 2 if
pernyataan itu tersebar menjadi 4 baris. Itu cukup bertele-tele, agak jelek ... Berani saya katakan, ini sangat tidak pythonic .
Apakah ada solusi lain yang lebih sederhana dan lebih ringkas? (dan lebih banyak lagi pythonic )
Ya, saya tahu saya dapat menggunakan if else
dalam satu baris, tetapi tidak dapat dibaca:
new_index = 0 if new_index < 0 else len(mylist) - 1 if new_index >= len(mylist) else new_index
Saya juga tahu saya bisa merangkai max()
dan min()
bersama. Lebih ringkas, tapi saya rasa agak kabur, lebih sulit menemukan bug jika saya salah mengetik. Dengan kata lain, saya tidak menganggapnya sangat mudah.
new_index = max(0, min(new_index, len(mylist)-1))
clamp = lambda value, minv, maxv: max(min(value, maxv), minv)
Menggunakan API dari arma.sourceforge.net/docs.html#clampJawaban:
Ini sebenarnya cukup jelas. Banyak orang mempelajarinya dengan cepat. Anda dapat menggunakan komentar untuk membantu mereka.
new_index = max(0, min(new_index, len(mylist)-1))
sumber
def clamp(n, smallest, largest): return max(smallest, min(n, largest))
helperFunctions.py
? Modul terpisah? Bagaimana jika ini dikotori dengan berbagai "fungsi pembantu" untuk hal yang sama sekali berbeda?utils.py
sorted((minval, value, maxval))[1]
sebagai contoh:
>>> 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
sumber
sorted()
. Sangat kompak, tetapi hanya sedikit tidak jelas. Bagaimanapun, selalu menyenangkan melihat solusi kreatif lainnya!min(max())
pembangunannya. Sangat sedikit lebih cepat jika angkanya berada dalam kisaran dan tidak diperlukan swap.banyak jawaban menarik di sini, semuanya hampir sama, kecuali ... mana yang lebih cepat?
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 memilikinya !, gunakan python ol biasa. Versi numpy, mungkin tidak mengherankan, adalah yang paling lambat dari semuanya. Mungkin karena mencari array, di mana versi lain hanya mengurutkan argumennya.
sumber
mm_clip
danpy_clip
akan sama cepatnya jika Anda menggunakan compiler JIT, seperti PyPy. Kecuali yang pertama lebih mudah dibaca, dan keterbacaan lebih penting dalam filosofi Python daripada sedikit peningkatan kinerja pada sebagian besar waktu.Lihat numpy.clip :
index = numpy.clip(index, 0, len(my_list) - 1)
sumber
clip
adalaha
, "array yang berisi elemen untuk dijepit". Jadi, Anda harus menulisnumpy.clip([index], …
, bukannumpy.clip(index, …
.Merantai
max()
danmin()
bersama adalah ungkapan normal yang pernah saya lihat. Jika Anda kesulitan membaca, tulis fungsi pembantu untuk merangkum operasi:def clamp(minimum, x, maximum): return max(minimum, min(x, maximum))
sumber
Apa yang terjadi dengan bahasa Python saya yang mudah dibaca? :-)
Serius, jadikan itu fungsi:
def addInRange(val, add, minval, maxval): newval = val + add if newval < minval: return minval if newval > maxval: return maxval return newval
kemudian sebut saja dengan sesuatu seperti:
val = addInRange(val, 7, 0, 42)
Atau solusi yang lebih sederhana dan lebih fleksibel di mana Anda melakukan penghitungan sendiri:
def restrict(val, minval, maxval): if val < minval: return minval if val > maxval: return maxval return val x = restrict(x+10, 0, 42)
Jika Anda mau, Anda bahkan dapat membuat daftar min / max sehingga terlihat lebih "murni secara matematis":
x = restrict(val+7, [0, 42])
sumber
min
danmax
jauh lebih jelas daripada sekumpulan persyaratan. (Saya tidak tahu untuk apaadd
- katakan sajaclamp(val + 7, 0, 42)
.)Yang ini tampaknya lebih pythonic bagi saya:
>>> def clip(val, min_, max_): ... return min_ if val < min_ else max_ if val > max_ else val
Beberapa tes:
>>> clip(5, 2, 7) 5 >>> clip(1, 2, 7) 2 >>> clip(8, 2, 7) 7
sumber
Jika kode Anda tampak terlalu berat, suatu fungsi mungkin membantu:
def clamp(minvalue, value, maxvalue): return max(minvalue, min(value, maxvalue)) new_index = clamp(0, new_index, len(mylist)-1)
sumber
Hindari menulis fungsi untuk tugas-tugas kecil seperti itu, kecuali jika Anda sering menerapkannya, karena akan mengacaukan kode Anda.
untuk nilai-nilai individu:
untuk daftar nilai:
map(lambda x: min(clamp_max, max(clamp_min, x)), values)
sumber