假设我有以下复选框:
<input type="checkbox" value="1-25" />
为了得到定义我正在寻找的范围边界的两个数字,我使用下面的jQuery:
var value = $(this).val();
var lowEnd = Number(value.split('-')[0]);
var highEnd = Number(value.split('-')[1]);
然后,我如何创建一个包含lowEnd和highEnd之间的所有整数的数组,包括lowEnd和highEnd本身?对于这个特定的例子,显然,结果数组将是:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
function range(j, k) {
return Array
.apply(null, Array((k - j) + 1))
.map(function(_, n){ return n + j; });
}
这大致相当于
function range(j, k) {
var targetLength = (k - j) + 1;
var a = Array(targetLength);
var b = Array.apply(null, a);
var c = b.map(function(_, n){ return n + j; });
return c;
}
分解一下:
var targetLength = (k - j) + 1;
var a = Array(targetLength);
这将创建一个具有正确标称长度的稀疏矩阵。现在,稀疏矩阵的问题是尽管它有正确的标称长度,但它没有实际的元素,所以,对于
j = 7, k = 13
console.log(a);
给了我们
Array [ <7 empty slots> ]
Then
var b = Array.apply(null, a);
将稀疏矩阵作为参数列表传递给Array构造函数,该构造函数生成一个(实际)长度为targetLength的密集矩阵,其中所有元素都具有未定义的值。第一个参数是数组构造函数执行上下文的“this”值,在这里没有作用,因此为null。
现在,
console.log(b);
收益率
Array [ undefined, undefined, undefined, undefined, undefined, undefined, undefined ]
最后
var c = b.map(function(_, n){ return n + j; });
利用了数组。映射函数通过:当前元素的值和2。当前元素的索引,映射委托/回调。第一个参数将被丢弃,而第二个参数在调整开始偏移量后可用于设置正确的序列值。
然后
console.log(c);
收益率
Array [ 7, 8, 9, 10, 11, 12, 13 ]
这里有3个函数,它们应该涵盖了我能想到的一切(包括对其他一些答案中的问题的修复):rangeInt(), range()和between()。在所有情况下都考虑升序和降序。
例子
范围英特()
包括端点并且只处理整数
rangeInt(1, 4) // [1, 2, 3, 4] Ascending order
rangeInt(5, 2) // [5, 4, 3, 2] Descending order
rangeInt(4, 4) // [4] Singleton set (i.e. not [4, 4])
rangeInt(-1, 1) // [-1, 0, 1] Mixing positive and negative
range ()
与rangeInt()相同,除了
不限于整数
允许在第三个参数中指定数量的点
range(0, 10, 2) // [0, 3.333, 6.666, 10] Gets endpoints and 2 points between
range(0, 1.5, 1) // [0, 0.75, 1.5] Accepts fractions
间()
与range()相同,除了
不包括端点
没有单例集(将返回一个空数组)
between(0, 10, 2) // [3.333, 6.666]
between(-1, -1.5) // [-1.25]
between(4, 4, 99) // []
源
/**
* Gets a set of integers that are evenly distributed along a closed interval
* @param {int} begin - Beginning endpoint (inclusive)
* @param {int} end - Ending endpoint (inclusive)
* @return {Array} Range of integers
*/
function rangeInt( begin, end ) {
if ( !Number.isInteger(begin) || !Number.isInteger(end) ) {
throw new Error('All arguments must be integers')
}
return range(begin, end, Math.abs(end - begin) - 1)
}
/**
* Gets a set of numbers that are evenly distributed along a closed interval
* @param {Number} begin - Beginning endpoint (inclusive)
* @param {Number} end - Ending endpoint (inclusive)
* @param {int} points - How many numbers to retrieve from the open interval
* @return {Array} Range of numbers
*/
function range( begin, end, points ) {
if ( begin !== end ) {
return [ begin, ...between(begin, end, points), end ]
}
else if ( Number.isFinite(begin) ) {
return [ begin ] // singleton set
}
else throw new Error('Endpoints must be finite')
}
/**
* Gets a subset of numbers that are evenly distributed along an open interval
* @param {Number} begin - Beginning endpoint (exclusive)
* @param {Number} end - Ending endpoint (exclusive)
* @param {int} points - How many numbers to retrieve from the interval
* @return {Array} Retrieved numbers
*/
function between( begin, end, points = 1 ) {
if ( !Number.isFinite(begin) || !Number.isFinite(end) || !Number.isFinite(points) ) {
throw new Error('All arguments must be finite')
}
const set = []
// Skip if an open interval does not exist
if ( begin !== end ) {
const step = (end - begin) / (points + 1)
for ( let i = 0; i < points; i++ ) {
set[i] = begin + (i + 1) * step
}
}
return set
}