我正在寻找以下方法的任何替代方法,以创建包含1到N的JavaScript数组,其中N仅在运行时已知。

var foo = [];

for (var i = 1; i <= N; i++) {
   foo.push(i);
}

对我来说,我觉得应该有一种不用循环的方法。


当前回答

这个问题有很多复杂的答案,但只有一句简单的话:

[...Array(255).keys()].map(x => x + 1)

此外,虽然上面的内容写起来很短(很整洁),但我认为下面的内容要快一点(最大长度:

127,国际8,

255,Uint8,

32767,国际16,

65535、Uint16、,

2147483647,国际32,

4294967295,Uint32。

(基于最大整数值),这里还有关于类型化数组的更多信息):

(new Uint8Array(255)).map(($,i) => i + 1);

虽然这个解决方案也不太理想,因为它创建了两个数组,并使用了额外的变量声明“$”(不确定使用这个方法有什么方法可以解决这个问题)。我认为以下解决方案是实现这一目标的最快方法:

for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;

在该语句之后的任何时候,您都可以在当前范围中简单地使用变量“arr”;

如果你想用它做一个简单的函数(带有一些基本的验证):

功能范围(最小、最大){min=min&&min.constructor==数字?最小值:0;!(max&&max.constructor==Number&&max>min)&&//布尔语句也可以用于void返回类型,如单行if语句。((最大值=最小值)&(最小值=0))//如果指定了一个“max”参数,那么首先检查它是否是一个数字,以及它是否大于min:如果是,保持不变;如果没有,那么就把它当作一开始没有“max”,“max”变为“min”(默认情况下,min变为0)对于(var i=0,arr=new(最大值<128?Int8阵列:最大值<256?Uint8阵列:最大值<32768?Int16阵列:最大值<65536?Uint16阵列:最大值<2147483648?Int32阵列:最大值<4294967296?Uint32阵列:大堆)(最大值-最小值);i<arr.length;i++)arr[i]=i+min;返回arr;}//如果需要,可以使用数组方法轻松循环range(1,11).forEach(x=>console.log(x));//或者如果你习惯了蟒蛇。。。在“你可以用”for。。。的“如果您需要单个值:对于(i范围(20202025))console.log(i);//或者如果你真的想用“for…”。。在“”中,您可以,但随后您只能访问密钥:对于(范围内的k(25,30))console.log(k);控制台日志(范围(1128).构造器名称,范围(200).构造器名称,范围(400900).结构名称,范围(33333).结构名称,范围(823100000).结构名称,range(10,4)//当“min”参数大于“max”时,它只会认为没有“max”,新的max变为“min”,“min”变为0,就好像“max”从未被写入);


因此,通过上述功能,上述超慢的“简单一行”变成了超快,甚至更短:

range(1,14000);

其他回答

如果您碰巧像我一样在应用程序中使用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]

查看本教程了解更多信息。

在ES6中:

Array.from({length: 1000}, (_, i) => i).slice(1);

或者更好(没有额外的变量_,也没有额外的切片调用):

Array.from({length:1000}, Number.call, i => i + 1)

或者,如果您的列表少于256个结果,您可以使用Uint8Array来获得稍快的结果(或者,您可以根据列表的长度使用其他Uint列表,例如Uint16的最大值为65535,或Uint32的最大值4294967295等。不过,正式地说,这些类型的数组只是在ES6中添加的)。例如:

Uint8Array.from({length:10}, Number.call, i => i + 1)

ES5:

Array.apply(0, {length: 1000}).map(function(){return arguments[1]+1});

或者,在ES5中,对于map函数(类似于上面ES6中Array.from函数的第二个参数),可以使用Number.call

Array.apply(0,{length:1000}).map(Number.call,Number).slice(1)

或者,如果你在这里也反对.sslice,你可以执行上面的ES5等效操作(来自ES6),比如:

Array.apply(0,{length:1000}).map(Number.call, Function("i","return i+1"))

填充Array的新方法是:

const array=[…array(5).keys()]console.log(数组)

结果将为:[0,1,2,3,4]

问题是这个技术的替代方案,但我想分享更快的方法。它与问题中的代码几乎相同,但它分配内存而不是使用push:

function range(n) {
    let a = Array(n);
    for (let i = 0; i < n; a[i++] = i);
    return a;
}

Fast

这个解决方案可能是最快的——它是由lodash_.range函数启发而来的(但我的更简单、更快)

设N=10,i=0,a=阵列(N);而(i<N)a[i++]=i;控制台日志(a);

与当前(2020.12.11)相比,基于while/for的现有答案的性能优势

内存在开始时由a=数组(N)分配一次使用了增加索引i++——看起来比减少索引i快30%左右——(可能是因为CPU缓存在正向上更快)

在此答案中,使用了20多种其他解决方案进行了速度测试