किसी सेगमेंट में नंबर को कैप करने का सबसे सुरुचिपूर्ण तरीका क्या है?


127

मान लेते हैं x, aऔर bसंख्याएँ हैं। मुझे xसेगमेंट की सीमा में कैप लगाने की जरूरत है [a, b]

मैं लिख सकता हूं Math.max(a, Math.min(x, b)), लेकिन मुझे नहीं लगता कि इसे पढ़ना बहुत आसान है। क्या किसी के पास इसे अधिक पठनीय तरीके से लिखने का एक चतुर तरीका है?

जवाबों:


197

जिस तरह से आप इसे करते हैं वह बहुत मानक है। आप एक उपयोगिता clampफ़ंक्शन को परिभाषित कर सकते हैं :

/**
 * Returns a number whose value is limited to the given range.
 *
 * Example: limit the output of this computation to between 0 and 255
 * (x * 255).clamp(0, 255)
 *
 * @param {Number} min The lower boundary of the output range
 * @param {Number} max The upper boundary of the output range
 * @returns A number in the range [min, max]
 * @type Number
 */
Number.prototype.clamp = function(min, max) {
  return Math.min(Math.max(this, min), max);
};

(हालांकि विस्तारित भाषा बिल्ट-इन आम तौर पर पर आधारित है)


OOps को आप मेरे टाइपो (
प्रतिचित्रित

5
नहीं, मुझे यह साइट से मिला है। के घोंसले / निष्पादन आदेश Math.minऔर Math.maxलंबे समय तक के पैरामीटर के रूप में के रूप में अप्रासंगिक है Math.minहै maxऔर के पैरामीटर Math.maxहै min
ओटो ऑलमडिंगर

23
देशी प्रोटोटाइप का विस्तार ( Number.prototypeइस मामले में) कई कारणों से बीमार है। देखें "बुरा तरीका: देशी प्रोटोटाइप का विस्तार" पर developer.mozilla.org/en-US/docs/Web/JavaScript/...
broofa

68

एक कम "गणित" उन्मुख दृष्टिकोण, लेकिन यह भी काम करना चाहिए, इस तरह से, </> परीक्षण उजागर हो जाता है (शायद न्यूनतम से अधिक समझ में आता है) लेकिन यह वास्तव में "पठनीय" से आपका क्या मतलब है पर निर्भर करता है

function clamp(num, min, max) {
  return num <= min ? min : num >= max ? max : num;
}

4
इस मुहावरे में <और> को <=> से बदलने के लिए बेहतर है, ताकि संभावित रूप से एक तुलना कम हो। उस सुधार के साथ, यह निश्चित रूप से मेरा पसंदीदा जवाब है: अधिकतम टकसाल भ्रमित और त्रुटि प्रवण हैं।
डॉन हैच

यह सबसे अच्छा जवाब है। ज्यादा तेज, ज्यादा सरल, ज्यादा पठनीय।
ट्रिस्टन नोव

5
यह तेज नहीं है। Math.min / मैक्सिमम सॉल्यूशन सबसे तेज jsperf.com/math-clamp/9
Manuel Di Iorio

1
@ मैन्यूलडायोरियो हुह? क्रोम के वर्तमान संस्करण के तहत, साधारण टर्नरी, Math.min / max के रूप में दोगुना है - और यदि आप अधिक महंगी Math.random()कॉल से ओवरहेड निकालते हैं, तो यह सरल दृष्टिकोण 10 x तेज है
mindplay.dk


48

ECMAScript 2017 के लिए अपडेट:

Math.clamp(x, lower, upper)

लेकिन ध्यान दें कि आज के अनुसार, यह स्टेज 1 का प्रस्ताव है । जब तक यह व्यापक रूप से समर्थित नहीं हो जाता, तब तक आप एक पॉलीफिल का उपयोग कर सकते हैं ।


4
यदि आप इस प्रस्ताव और अन्य को ट्रैक करना चाहते हैं, तो देखें: github.com/tc39/proposals
gfullam

5
मुझे यह प्रस्ताव tc39 / प्रस्तावों रेपो
कॉलिन डी

तलाश करने वालों के लिए, प्रस्ताव को "मठ एक्सटेंशन" के रूप में स्टेज 1 प्रस्तावों के तहत सूचीबद्ध किया गया है । वास्तविक प्रस्ताव यहां है: github.com/rwaldron/proposal-math-extensions
WickyNilliams

14
Math.clip = function(number, min, max) {
  return Math.max(min, Math.min(number, max));
}

2
यह समाधान वास्तव में तेजी से रास्ता है, हालांकि prototypeजब मैं वास्तव में फ़ंक्शन का उपयोग करने की बात करता हूं, तो मैं बहुत सुरुचिपूर्ण का विस्तार करने पर विचार करता हूं ।
मैक्सर्ट

11

यह "जस्ट-यूज़-ए-लाइब्रेरी" उत्तर नहीं बनना चाहता है, लेकिन यदि आप लॉडश का उपयोग कर रहे हैं तो आप इसका उपयोग कर सकते हैं .clamp:

_.clamp(yourInput, lowerBound, upperBound);

इसलिए कि:

_.clamp(22, -10, 10); // => 10

यहाँ इसका कार्यान्वयन लोदश स्रोत से लिया गया है :

/**
 * The base implementation of `_.clamp` which doesn't coerce arguments.
 *
 * @private
 * @param {number} number The number to clamp.
 * @param {number} [lower] The lower bound.
 * @param {number} upper The upper bound.
 * @returns {number} Returns the clamped number.
 */
function baseClamp(number, lower, upper) {
  if (number === number) {
    if (upper !== undefined) {
      number = number <= upper ? number : upper;
    }
    if (lower !== undefined) {
      number = number >= lower ? number : lower;
    }
  }
  return number;
}

इसके अलावा, यह ध्यान देने योग्य है कि लॉडश एकल तरीकों को स्टैंडअलोन मॉड्यूल के रूप में उपलब्ध करता है, इसलिए यदि आपको केवल इस पद्धति की आवश्यकता है, तो आप इसे बाकी पुस्तकालय के बिना भी स्थापित कर सकते हैं:

npm i --save lodash.clamp

6

यदि आप es6 एरो फ़ंक्शंस का उपयोग करने में सक्षम हैं, तो आप आंशिक अनुप्रयोग दृष्टिकोण का भी उपयोग कर सकते हैं:

const clamp = (min, max) => (value) =>
    value < min ? min : value > max ? max : value;

clamp(2, 9)(8); // 8
clamp(2, 9)(1); // 2
clamp(2, 9)(10); // 9

or

const clamp2to9 = clamp(2, 9);
clamp2to9(8); // 8
clamp2to9(1); // 2
clamp2to9(10); // 9

हर बार जब आप एक संख्या को दबाना चाहते हैं, तो एक फ़ंक्शन का निर्माण बहुत ही अक्षम दिखता है
जॉर्ज

1
संभवतः आपके उपयोग के मामले पर निर्भर करता है। यह एक सेट रेंज के साथ क्लैंप बनाने के लिए सिर्फ एक फैक्ट्री फ़ंक्शन है। आप एक बार बना सकते हैं और अपने पूरे ऐप में पुन: उपयोग कर सकते हैं। कई बार बुलाया जाना जरूरी नहीं है। सभी उपयोग मामलों के लिए उपकरण भी नहीं हो सकता है जहाँ आपको एक निर्धारित सीमा में लॉक करने की आवश्यकता नहीं है।
बिंगल्स

@George अगर आपको रेंज रखने की ज़रूरत नहीं है, तो केवल आंतरिक तीर फ़ंक्शन को हटा दें और मान पैरामीटर को बाहरी तीर फ़ंक्शन पर ले जाएं
Alisson Nunes

6

यदि आप किसी फंक्शन को परिभाषित नहीं करना चाहते हैं, तो इसे लिखना Math.min(Math.max(x, a), b)उतना बुरा नहीं है।


0

तीर कामुकता की भावना में, आप एक माइक्रो क्लैंप / बाधा / गेट / & c बना सकते हैं। बाकी मापदंडों का उपयोग करते हुए कार्य करें

var clamp = (...v) => v.sort((a,b) => a-b)[1];

फिर बस तीन मूल्यों में पास करें

clamp(100,-3,someVar);

यही है, फिर से, अगर सेक्सी द्वारा, आप 'लघु' का मतलब है


clampयदि आप जटिल तर्क रखते हैं, तो आप
एरर्स का

0

यह अगर / अन्यथा जो टेर्नेरी विकल्प के बराबर है पर टर्नरी विकल्प का विस्तार करता है, लेकिन पठनीयता का त्याग नहीं करता है।

const clamp = (value, min, max) => {
  if (value < min) return min;
  if (value > max) return max;
  return value;
}

35b (या 43b का उपयोग करने पर function) न्यूनतम करता है :

const clamp=(c,a,l)=>c<a?a:c>l?l:c;

इसके अलावा, आप किस टूल या ब्राउजर का उपयोग करते हैं, इस पर निर्भर करता है कि आपको मैथ आधारित कार्यान्वयन या टर्नरी आधारित कार्यान्वयन तेज है या नहीं। लगभग उसी प्रदर्शन के मामले में, मैं पठनीयता का विकल्प चुनूंगा।


-5

मेरा मनपसंद:

[min,x,max].sort()[1]

12
डाउनवोटिंग क्योंकि यह काम नहीं करता है। [1,5,19].sort()[1]19. यह इस तरह तय किया जा सकता है: [min,x,max].sort(function(a, b) { return a - b; })[1]लेकिन यह अब सेक्सी नहीं है। जब भारी इस्तेमाल किया जाता है, तो यह केवल तीन नंबरों की तुलना करने के लिए एक नया सरणी बनाने के लिए एक प्रदर्शन मुद्दा हो सकता है।
कायहार

5
इस +1 को वैसे भी देना, क्योंकि सेक्सी वह है जो मायने रखता है।
डॉन हैच

3
IMHO यह किसी भी अन्य विकल्पों की तुलना में कहीं अधिक पठनीय है, विशेष रूप से तीर के कार्यों के साथ:[min, x, max].sort((a,b) => a-b)[1]
zaius

4
इसका कारण यह हमेशा काम नहीं करता है क्योंकि सॉर्ट विधि संख्यात्मक मानों की तुलना ठीक से नहीं करती है। (यह उन्हें स्ट्रिंग्स की तरह मानता है)
जॉन लेउन्हेगन

मुझे लगता है कि एक उपयुक्त नाम वाले फ़ंक्शन की तुलना में कुछ भी कामुक नहीं है जो काम को कुशलतापूर्वक और स्पष्ट रूप से सही तरीके से करता है। लेकिन यह स्वाद का मामला हो सकता है।
बॉलपॉइंटबैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.