Frage Was ist der eleganteste Weg, um eine Nummer an ein Segment zu kappen?


Sagen wir x, a und b sind Zahlen. Ich muss schließen x zu den Grenzen des Segments [a, b].

ich kann schreiben Math.max(a, Math.min(x, b)), aber ich glaube nicht, dass es sehr einfach zu lesen ist. Hat jemand eine schlaue Art, dies lesbarer zu schreiben?


75
2017-07-10 08:58


Ursprung


Antworten:


Die Art, wie Sie es tun, ist ziemlich Standard. Sie können ein Dienstprogramm definieren clamp funktionieren wie beschrieben Hier:

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

(Obwohl das Erweitern von Sprach-Einbauten generell verpönt ist)


141
2017-07-10 09:02



ein weniger "Math" orientierter Ansatz, sollte aber auch funktionieren, so wird der </> Test herausgestellt (vielleicht verständlicher als Minimaxing) aber es kommt wirklich darauf an, was du mit "lesbar" meinst

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

39
2017-07-10 09:10



Update für ECMAScript 2017:

Math.clamp(x, lower, upper)

Aber beachte, dass es ab heute eine Stufe 1 ist Vorschlag. Bis es weit verbreitet ist, können Sie ein verwenden Polyfill.


19
2017-09-13 19:50



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

10
2017-07-10 09:03



Im Geiste des Pfeils Sexiness könntest du ein Mikro machen klemmen / beschränken / Gate / & c. Funktion mit Ruheparametern

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

Dann gebe einfach drei Werte ein

clamp(100,-3,someVar);

Das heißt, wenn du sexy bist, meinst du "kurz"


3
2018-04-26 18:15



Dies soll keine "Just-Use-A-Library" -Antwort sein, sondern nur für den Fall, dass Sie Underscore / Lodash verwenden .clamp:

_.clamp(yourInput, lowerBound, upperBound);

Damit:

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

Hier ist seine Implementierung, von Lodash übernommen Quelle:

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

Es ist auch erwähnenswert, dass Lodash einzelne Methoden als eigenständige Module zur Verfügung stellt. Falls Sie nur diese Methode benötigen, können Sie sie einfach ohne den Rest der Bibliothek installieren:

npm i --save lodash.clamp

3
2017-11-03 17:36



Wenn Sie ES6-Pfeilfunktionen verwenden können, können Sie auch einen partiellen Anwendungsansatz verwenden:

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

2
2017-11-02 20:46



Sie können das auch wiederverwendbar verwenden Nummer-Klemm-Komponente was eine Zahl zurückgibt, deren Wert auf den angegebenen Bereich beschränkt ist.

Beispiel:

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

Wie es funktioniert:

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

1
2018-06-05 08:26



Wenn Sie keine Funktion definieren möchten, schreiben Sie sie wie Math.min(Math.max(x, a), b) ist nicht so schlimm.


0
2018-02-15 17:44



Mein Favorit:

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

-1
2018-03-04 19:15