javascript standard Quelle est la manière la plus élégante de plafonner un nombre à un segment?



javascript standard (8)

une approche moins "mathématique", mais devrait aussi fonctionner, de cette façon, le test </> est exposé (peut-être plus compréhensible que minimaxing) mais cela dépend vraiment de ce que vous entendez par "lisible"

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

Disons que x , a et b sont des nombres. J'ai besoin de plafonner x aux limites du segment [a, b] .

Je peux écrire Math.max(a, Math.min(x, b)) , mais je ne pense pas que ce soit très facile à lire. Quelqu'un a-t-il une manière intelligente d'écrire ceci d'une manière plus lisible?


Answer #1

Vous pouvez également utiliser ce composant de pince numérique réutilisable qui renvoie un nombre dont la valeur est limitée à la plage donnée.

Exemple:

clamp(50, 5, 10) // => 5

Comment ça marche:

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

Answer #2

La façon dont vous le faites est assez standard. Vous pouvez définir une fonction de clamp utilitaire comme décrit here :

/**
 * 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);
};

(Bien que l'extension de la langue intégrée soit généralement désapprouvée)


Answer #3

Cela ne veut pas être une réponse "juste-utiliser-une-bibliothèque" mais juste au cas où vous utilisez Underscore / Lodash vous pouvez utiliser .clamp :

_.clamp(yourInput, lowerBound, upperBound);

Pour que:

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

Voici sa mise en œuvre, tirée de la source Lodash:

/**
 * 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;
}

En outre, il est à noter que Lodash rend les méthodes simples disponibles en tant que modules autonomes, donc si vous avez seulement besoin de cette méthode, vous pouvez simplement l'installer sans le reste de la bibliothèque:

npm i --save lodash.clamp

Answer #4

Dans l'esprit de sex-appeal flèche, vous pouvez créer une pince micro / contrainte / porte / & c. Fonction utilisant des paramètres de repos

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

Ensuite, passez juste trois valeurs

clamp(100,-3,someVar);

C'est, encore une fois, si par sexy, vous voulez dire «court»


Answer #5

Si vous ne voulez pas définir de fonction, l'écrire comme Math.min(Math.max(x, a), b) n'est pas si mauvais.


Answer #6

Si vous pouvez utiliser les fonctions de flèche es6, vous pouvez également utiliser une approche d'application partielle:

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

Answer #7

Mise à jour pour ECMAScript 2017:

Math.clamp(x, lower, upper)

Mais notez qu'à ce jour, c'est une proposal étape 1. Jusqu'à ce qu'il soit largement supporté, vous pouvez utiliser un polyfill .





coding-style