Laten we zeggen dat x
, a
en b
getallen zijn. Ik moet x
beperken tot de grenzen van het segment [a, b]
.
Met andere woorden, ik heb een klemfunctienodig:
clamp(x) = max( a, min(x, b) )
Kan iemand hier een beter leesbare versie van bedenken?
Antwoord 1, autoriteit 100%
De manier waarop je het doet is vrij standaard. U kunt een hulpprogramma clamp
-functie definiëren:
/**
* 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);
};
(Hoewel het uitbreiden van ingebouwde taal over het algemeen afgekeurd wordt)
Antwoord 2, autoriteit 36%
een minder “wiskunde”-georiënteerde benadering, maar zou ook moeten werken, op deze manier wordt de <
/ >
-test zichtbaar (misschien begrijpelijker dan minimaxen) maar het hangt er echt van af wat je bedoelt met “leesbaar”
function clamp(num, min, max) {
return num <= min
? min
: num >= max
? max
: num
}
Antwoord 3, autoriteit 28%
Er is een voorstel om een toevoeging aan het ingebouwde Math
-object toe te voegen om dit te doen:
Math.clamp(x, lower, upper)
Maar houd er rekening mee dat het vanaf vandaag een fase 1 voorstel. Totdat het breed wordt ondersteund (wat niet gegarandeerd is), kunt u een polyfillgebruiken een>.
Antwoord 4, autoriteit 13%
Een eenvoudige manier zou zijn om
Math.max(min, Math.min(number, max));
en je kunt natuurlijk een functie definiëren die dit omhult:
function clamp(number, min, max) {
return Math.max(min, Math.min(number, max));
}
Oorspronkelijk heeft dit antwoord de bovenstaande functie ook toegevoegd aan het globale Math
-object, maar dat is een overblijfsel uit een vervlogen tijdperk, dus het is verwijderd (bedankt @Aurelio voor de suggestie)
Antwoord 5, autoriteit 6%
Dit wil geen “gewoon-gebruik-een-bibliotheek”-antwoord zijn, maar voor het geval je Lodash gebruikt, kun je .clamp
:
_.clamp(yourInput, lowerBound, upperBound);
Zodat:
_.clamp(22, -10, 10); // => 10
Hier is de implementatie, overgenomen uit Lodash bron:
/**
* 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;
}
Het is ook vermeldenswaard dat Lodash afzonderlijke methoden beschikbaar stelt als zelfstandige modules, dus als u alleen deze methode nodig heeft, kunt u deze installeren zonder de rest van de bibliotheek:
npm i --save lodash.clamp
Antwoord 6, autoriteit 4%
Als u es6-pijlfuncties kunt gebruiken, kunt u ook een gedeeltelijke applicatiebenadering gebruiken:
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
Antwoord 7, autoriteit 3%
Als je geen functie wilt definiëren, is het niet zo erg om het als Math.min(Math.max(x, a), b)
te schrijven.
Antwoord 8
Dit breidt de ternaire optie uit tot if/else, wat gelijk is aan de ternaire optie, maar de leesbaarheid niet in gevaar brengt.
const clamp = (value, min, max) => {
if (value < min) return min;
if (value > max) return max;
return value;
}
Verkleint tot 35b (of 43b bij gebruik van function
):
const clamp=(c,a,l)=>c<a?a:c>l?l:c;
Ook, afhankelijk van de perf-tooling of browser die u gebruikt, krijgt u verschillende resultaten of de op wiskunde gebaseerde implementatie of ternaire implementatie sneller is. Bij ongeveer dezelfde prestaties zou ik kiezen voor leesbaarheid.
Antwoord 9
In de geest van pijl-sexiness, zou je een micro kunnen maken
klem/beperking/poort/&c. functie met behulp van rustparameters
var clamp = (...v) => v.sort((a,b) => a-b)[1];
Geef dan gewoon drie waarden door
clamp(100,-3,someVar);
Dat wil zeggen, nogmaals, als je met sexy ‘kort’ bedoelt
Antwoord 10
Mijn favoriet:
[min,x,max].sort()[1]