我正在寻找以下方法的任何替代方法,以创建包含1到N的JavaScript数组,其中N仅在运行时已知。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
对我来说,我觉得应该有一种不用循环的方法。
我正在寻找以下方法的任何替代方法,以创建包含1到N的JavaScript数组,其中N仅在运行时已知。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
对我来说,我觉得应该有一种不用循环的方法。
当前回答
使用不修改Number.prototype的生成器函数的可移植版本。
函数序列(最大值,步长=1){返回{[Symbol.iiterat]:函数*(){对于(设i=1;i<=max;i+=步长),得出i}}}console.log([…序列(10)])
其他回答
我发现了这条旧线索,因为我自己也在想同样的问题,但我想这里没有一个答案比Kokodoko评论的原始示例更容易,哈哈!
我最终自己使用了这个方法:
var foo = [];
while (foo.length < N)
foo.push( foo.length + 1 );
这至少比常规的for循环稍微快一点,而且希望不容易出错(尽管在计算上可能更昂贵)。
甚至可以做以下事情:
var foo= [];
while (foo.length < N)
foo.push( foo.length%4 + 1 );
以按顺序将阵列填充1-4次。或者使用此方法用单个项填充数组,尽管我想在这种情况下,只使用array(N).fill(x)可能会更快。
您可以这样做:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
结果:[0,1,2,3,4,5,6,7,8,9]
或具有随机值:
Array.apply(null, {length: N}).map(Function.call, Math.random)
结果:[0.782694901619107,0.9572225909214467,0.8586748542729765,0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.5577575915958732, 0.16363654541783035]
解释
首先,注意Number.call(undefined,N)等同于Number(N),它只返回N。我们稍后将使用这个事实。
Array.apply(null,[undefined,undefineed,undefinded])等同于Array(undefine,undefine,undefide),它生成一个三元素数组,并为每个元素分配undefine。
如何将其推广到N个元素?考虑一下Array()的工作原理,大致如下:
function Array() {
if ( arguments.length == 1 &&
'number' === typeof arguments[0] &&
arguments[0] >= 0 && arguments &&
arguments[0] < 1 << 32 ) {
return [ … ]; // array of length arguments[0], generated by native code
}
var a = [];
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
return a;
}
自ECMAScript 5以来,Function.pr原型.apply(thisArg,argsArray)也接受鸭子类型的类似数组的对象作为其第二个参数。如果我们调用Array.apply(null,{length:N}),那么它将执行
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
现在我们有一个N元素数组,每个元素都设置为undefined。当我们对其调用.map(callback,thisArg)时,每个元素都将被设置为callback.call(thisArg,element,index,array)的结果。因此,[未定义,未定义,…,未定义].map(Number.call,Number)会将每个元素映射到(Number.call).call(Number,undefined,index,array),这与Number.ccall(undefineed,index,array)相同,正如我们之前所观察到的,它的计算结果为index。这就完成了元素与其索引相同的数组。
为什么要解决Array.apply(null,{length:N})而不是Array(N)的问题?毕竟,这两个表达式都会产生一个未定义元素的N元素数组。不同之处在于,在前一个表达式中,每个元素都被显式设置为undefined,而在后一个表达式,每个元素从未被设置。根据.map()的文档:
回调仅对已赋值数组的索引调用;对于已删除或从未赋值的索引,不会调用它。
因此,Array(N)不足;数组(N).map(Number.call,Number)将导致长度为N的未初始化数组。
兼容性
由于该技术依赖于ECMAScript 5中指定的Function.protype.apply()的行为,因此它在之前的ECMAScript5浏览器(如Chrome 14和Internet Explorer 9)中不起作用。
这可能是生成数字数组的最快方法
最短的
var a=[],b=N;while(b--)a[b]=b+1;
内联
var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]
如果您想从1开始
var arr=(function(a,b){while(a--)b[a]=a+1;return b})(10,[]);
//arr=[1,2,3,4,5,6,7,8,9,10]
想要功能吗?
function range(a,b,c){c=[];while(a--)c[a]=a+b;return c}; //length,start,placeholder
var arr=range(10,5);
//arr=[5,6,7,8,9,10,11,12,13,14]
WHY?
while是最快的循环直接设置比推送更快[]比新阵列(10)更快它很短。。。查看第一个代码。然后看看这里的所有其他函数。
如果你喜欢,就不能没有
for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]
or
for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
为了好玩,我想借鉴伊恩·亨利的答案。
当然,var array=new array(N);将为您提供大小为N的数组,但键和值将相同。。。。然后,要将数组缩短为M大小,请使用array.length=M…但对于一些添加的功能,请尝试:
function range()
{
// This function takes optional arguments:
// start, end, increment
// start may be larger or smaller than end
// Example: range(null, null, 2);
var array = []; // Create empty array
// Get arguments or set default values:
var start = (arguments[0] ? arguments[0] : 0);
var end = (arguments[1] ? arguments[1] : 9);
// If start == end return array of size 1
if (start == end) { array.push(start); return array; }
var inc = (arguments[2] ? Math.abs(arguments[2]) : 1);
inc *= (start > end ? -1 : 1); // Figure out which direction to increment.
// Loop ending condition depends on relative sizes of start and end
for (var i = start; (start < end ? i <= end : i >= end) ; i += inc)
array.push(i);
return array;
}
var foo = range(1, -100, 8.5)
for(var i=0;i<foo.length;i++){
document.write(foo[i] + ' is item: ' + (i+1) + ' of ' + foo.length + '<br/>');
}
上述输出:
1是第1项,共12项-7.5为第2项,共12项-16是第3项,共12项-24.5为第4项,共12项-33是第5项,共12项-41.5是第6项,共12项-50是第7项,共12项-58.5为第8项,共12项-67是第9项,共12项-75.5为第10项,共12项-84是第11项,共12项-92.5是第12项,共12项
jsFiddle示例
此函数使用自动生成的参数数组。
该函数创建一个数组,该数组中的值以大小增量开始,以大小增量结束,其中
range(start, end, increment);
每个值都有一个默认值,增量的符号无关紧要,因为增量的方向取决于开始和结束的相对大小。
如果您碰巧像我一样在应用程序中使用d3.js,d3会提供一个助手函数来为您执行此操作。
因此,要获得从0到4的数组,非常简单:
d3.range(5)
[0, 1, 2, 3, 4]
并获得从1到5的数组,如您所请求的:
d3.range(1, 5+1)
[1, 2, 3, 4, 5]
查看本教程了解更多信息。