比方说x
,a
和b
是数字。我需要x
限制该部分的范围[a, b]
。
我会写Math.max(a, Math.min(x, b))
,但我认为它不容易阅读。有没有人有一个聪明的方法来以更具可读性的方式编写它?
比方说x
,a
和b
是数字。我需要x
限制该部分的范围[a, b]
。
我会写Math.max(a, Math.min(x, b))
,但我认为它不容易阅读。有没有人有一个聪明的方法来以更具可读性的方式编写它?
Answers:
您的操作方式非常标准。您可以定义一个实用程序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);
};
(尽管通常不支持扩展语言内置功能)
Math.min
和Math.max
是无关紧要的,只要的参数Math.min
是max
和的参数Math.max
是min
。
Number.prototype
出于多种原因,不建议扩展本机原型(在这种情况下)。请参阅developer.mozilla.org/en-US/docs/Web/JavaScript/…上的
一种不太以“数学”为导向的方法,但也应该起作用,这样,测试就暴露了(可能比minimaxing更容易理解),但这实际上取决于您对“可读”的理解。
function clamp(num, min, max) {
return num <= min ? min : num >= max ? max : num;
}
Math.random()
调用中消除开销,则这种简单的方法会快10倍。
Math.clip = function(number, min, max) {
return Math.max(min, Math.min(number, max));
}
prototype
实际使用该功能时非常优雅的。
这并不想成为一个“随便使用一个库”的答案,但是如果万一您正在使用Lodash,则可以使用.clamp
:
_.clamp(yourInput, lowerBound, upperBound);
以便:
_.clamp(22, -10, 10); // => 10
这是它的实现,取自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;
}
另外,值得注意的是,Lodash使单个方法可以作为独立模块使用,因此,如果仅需要此方法,则可以安装它而无需使用库的其余部分:
npm i --save lodash.clamp
如果您能够使用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
本着箭头性感的精神,您可以创建一个微型钳/约束/门/&c。使用剩余参数的功能
var clamp = (...v) => v.sort((a,b) => a-b)[1];
然后只需传入三个值
clamp(100,-3,someVar);
就是说,再次,如果是性感的话,你的意思是“短”
clamp
如果您具有复杂的逻辑(即使它是“性感”的话),perf也会受到严重打击
这将三元选项扩展为if / else,它的最小值与三元选项等效,但不牺牲可读性。
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;
另外,根据您使用的性能工具或浏览器,您会发现基于Math的实现或基于三元的实现更快的各种结果。在性能大致相同的情况下,我会选择可读性。
我的最爱:
[min,x,max].sort()[1]
[1,5,19].sort()[1]
返回19.可以像这样修复:[min,x,max].sort(function(a, b) { return a - b; })[1]
但这不再性感了。除了经常使用之外,创建一个仅用于比较三个数字的数组可能是性能问题。
[min, x, max].sort((a,b) => a-b)[1]