কিছু পরিসরে একটি পূর্ণসংখ্যা বাতা কিভাবে?


94

আমার কাছে নিম্নলিখিত কোড রয়েছে:

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লাইনে বিভক্ত 2 টি স্টেটমেন্ট লিখতে হবে । এটি বেশ ভার্জোজ, কিছুটা কুরুচিপূর্ণ ... আমি সাহস করে বলি, এটি বেশ অ-পাইথোনিক

অন্য কোন সহজ এবং আরও কমপ্যাক্ট সমাধান আছে? (এবং আরও অজগর )

হ্যাঁ, আমি জানি আমি 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))

4
যদি এটি "কিন্ডা অস্পষ্ট" বোধ করে, তবে এটি থেকে কোনও ফাংশন তৈরি করবেন?
সান্তা

4
হ্যাঁ, আমি একটি ফাংশন লিখতে পারি, তবে এটি বিন্দু নয়। প্রশ্নটি কীভাবে কার্যকর করা যায় (হয় ইনলাইন বা কোনও কার্যক্রমে)।
ডেনিলসন সা মিয়া

clamp = lambda value, minv, maxv: max(min(value, maxv), minv)Arma.sourceforge.net/docs.html#clamp-
Dima Tisnek

উত্তর:


121

এটি আসলে বেশ পরিষ্কার। অনেক লোকেরা এটি দ্রুত শিখে ফেলে। আপনি তাদের মন্তব্য করতে একটি মন্তব্য ব্যবহার করতে পারেন।

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

12
যদিও আমি অনুভব করি যে এটি হওয়া উচিত ঠিক তেমন পাইথন নয়, তবে আমি এখন আমাদের কাছে এটিই সেরা সমাধান বলে মনে করি।
ডেনিলসন সা মিয়া

50
def clamp(n, smallest, largest): return max(smallest, min(n, largest))
সিএসএল

4
@ সিএসএল লোকেরা সর্বদা এই ছোট সহায়ক সাহায্যকারী কার্যাদি সরবরাহ করে তবে আমি সেগুলি কোথায় রাখব তা কখনই জানি না। helperFunctions.py? একটি পৃথক মডিউল? পুরোপুরি ভিন্ন জিনিসের জন্য যদি এটি বিভিন্ন "সহায়ক সহায়ক" দিয়ে জঞ্জাল হয়ে যায় তবে কী হবে?
মতিন উলহাক

4
আমি জানি না, তবে আপনি যদি এগুলি প্রচুর সংগ্রহ করেন এবং সেগুলি বুদ্ধিমান মডিউলগুলিতে শ্রেণিবদ্ধ করেন, তবে কেন গিটহাব লাগিয়ে তা থেকে পিপিআই প্যাকেজ তৈরি করবেন না? সম্ভবত জনপ্রিয় হবে।
সিএসএল


90
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

12
sorted()অন্তর্নির্মিত সৃজনশীল ব্যবহারের জন্য +1 । খুব কমপ্যাক্ট তবে এটি কিছুটা অস্পষ্ট। যাইহোক, অন্যান্য সৃজনশীল সমাধানগুলি দেখতে সর্বদা সুন্দর!
ডেনিলসন সা মায়া

12
খুব সৃজনশীল, এবং প্রকৃতপক্ষে min(max())নির্মাণের মতো দ্রুত । সংখ্যাটি সীমার মধ্যে রয়েছে এবং কোনও অদলবদলের প্রয়োজন নেই সে ক্ষেত্রে খুব সামান্য দ্রুত।
0:44

41

এখানে অনেক আকর্ষণীয় উত্তর, একইগুলি ব্যতীত ... কোনটি দ্রুত?

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

প্যাক্সিডিয়াবলোতে এটি আছে! অদ্ভুত সংস্করণটি সম্ভবত অবাক হওয়ার মতো নয়, প্রচুর ধীরতম। সম্ভবত কারণ এটি অ্যারেগুলি খুঁজছে, যেখানে অন্যান্য সংস্করণগুলি কেবল তাদের যুক্তি অর্ডার করে।


7
@ লেনারহয়েট এটি বিস্ময়কর নয়, বিবেচনা করে যে নম্পির অভিনয় একক সংখ্যা নয়, বড় অ্যারে ঘিরে তৈরি করা হয়েছে। এছাড়াও, এটি পূর্বে পূর্ণসংখ্যাটি একটি অভ্যন্তরীণ ডেটাটাইপগুলিতে রূপান্তর করতে হয় এবং এটি বিভিন্ন ধরণের ইনপুট গ্রহণ করে, ইনপুটটি কী ধরণের এবং এটি কী রূপান্তর করতে পারে তা নির্ধারণ করতে সম্ভবত যথেষ্ট সময় লাগে। আপনি কয়েক হাজার মানকে একটি অ্যারে (পছন্দসইভাবে তালিকা বা টুপল নয়, যা এটি প্রথমে রূপান্তর করতে হবে) খাওয়ালে আপনি আরও ভাল নম্পি পারফরম্যান্স দেখতে পাবেন।
blubberdiblub

পাইথনটি তিনটি ক্রমান্বয়ের অর্ডার। 783 এনএস = 783,000 ডলার। অতীতেও আমি একই ভুল করেছি। স্বরলিপি সূক্ষ্ম।
ডাস্টিন অ্যান্ড্রুজ

7
@ ডাস্টিনএন্ড্রুজ আপনি এটি পিছনে পেয়েছেন। 1 µ গুলি 10 ^ -6 সেকেন্ড, 1 এনএস 10 ^ -9 সেকেন্ড। অজগর উদাহরণটি 0.784 in এস এ 1 লুপটি সম্পূর্ণ করে। বা কমপক্ষে, এটি আমার পরীক্ষিত মেশিনে করেছে। এই মাইক্রোবেঞ্চমার্কটি অন্য যে কোনও মাইক্রোব্যাঙ্কমার্কের মতোই কার্যকর; এটি আপনাকে সত্যিকারের খারাপ ধারণা থেকে দূরে রাখতে পারে তবে দরকারী কোডটি লেখার পক্ষে সবচেয়ে দ্রুততম উপায় খুঁজে পেতে আপনাকে সম্ভবত সাহায্য করবে না ।
সিঙ্গেলাইজেশন ইলিমিনেশন

ফাংশনগুলির কলটিতে সামান্য ওভারহেড রয়েছে। আমি মাপদণ্ডটি করিনি, তবে এটি পিআইপি এর মতো আপনি জেআইটি সংকলক ব্যবহার করেন তবে এটি যথেষ্ট সম্ভব mm_clipএবং এটিও py_clipসমানভাবে দ্রুত হবে। পূর্ববর্তীটি আরও পাঠযোগ্য, এবং পাইথনের দর্শনে পঠনযোগ্যতা বেশিরভাগ সময় সামান্য পারফরম্যান্স অর্জনের চেয়ে গুরুত্বপূর্ণ Ex
হাইস্টেকার

@ ডাস্টিনএন্ড্রুজ আমি আপনার সত্যিকারের ভুল মন্তব্য মুছে ফেলার পরামর্শ দিচ্ছি কারণ আপনি এটি পিছনের দিকে পেয়েছিলেন।
একিউম্যানাস

38

Numpy.clip দেখুন :

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

দস্তাবেজগুলি বলে যে এর প্রথম প্যারামিটারটি clipহ'ল a"ক্লিপ করার উপাদানগুলিতে থাকা অ্যারে"। সুতরাং আপনি লিখতে হবে numpy.clip([index], …, না numpy.clip(index, …
ররি ও'কেন

13
@ ররিও'কেন: আপনি কি চেষ্টা করে দেখেছেন?
নীল জি

4
পান্ডারা সিরিজ এবং ডেটাফ্রেমস এবং প্যানেলগুলিতে এটিকে মঞ্জুরি দেয়।
নুর ওল্ফ

19

শৃঙ্খলাবদ্ধ max()এবং min()একসাথে হ'ল আমি যে সাধারণ প্রতিমাটি দেখেছি। আপনি যদি পড়তে অসুবিধা পান তবে অপারেশনটি encapsulate করতে একটি সহায়ক ফাংশন লিখুন:

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

14

আমার প্রিয় পাঠযোগ্য পাইথন ভাষার যা কিছু ঘটেছে? :-)

সিরিয়াসলি, কেবল এটি একটি ফাংশন করুন:

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

6
এটি একটি ফাংশনে রাখা ভাল (এবং পরামর্শ দেওয়া হয়েছে, আপনি যদি এটি অনেক কিছু করে থাকেন) তবে আমি মনে করি minএবং শর্তাবলীর maxএকগুচ্ছের চেয়ে অনেক পরিষ্কার। (আমি কী জানি তার addজন্য - শুধু বলি clamp(val + 7, 0, 42)))
গ্লেন মেইনার্ড

4
@ গ্লেনমায়নার্ড নিশ্চিত নই যে আমি ন্যূনতম এবং সর্বাধিক পরিষ্কার er এগুলি ব্যবহারের পুরো বিন্দুটি হ'ল কার্যকরভাবে কোডটিকে কম স্পষ্ট করে তোলে এমন একটি লাইনে আরও স্টাফ তৈরি করতে সক্ষম হওয়া।
ম্যাড পদার্থবিজ্ঞানী

11

এটিকে আমার কাছে আরও অজানা মনে হচ্ছে:

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

8

যদি আপনার কোডটি খুব অযৌক্তিক মনে হয় তবে কোনও ক্রিয়াকলাপ সাহায্য করতে পারে:

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

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

2

আপনি যদি এগুলি প্রায়শই প্রয়োগ না করেন তবে এগুলি আপনার কোডটিকে বিশৃঙ্খল করে তুলবে এ জাতীয় ছোট কাজের জন্য ফাংশনগুলি লিখতে এড়িয়ে চলুন।

স্বতন্ত্র মূল্যবোধের জন্য:

min(clamp_max, max(clamp_min, value))

মান তালিকার জন্য:

map(lambda x: min(clamp_max, max(clamp_min, x)), values)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.