我正在寻找以下方法的任何替代方法,以创建包含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);
}
对我来说,我觉得应该有一种不用循环的方法。
当前回答
在ES6中,使用Array from()和key()方法。
Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
使用排列运算符的较短版本。
[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
从1开始,将map函数传递给Array from(),对象具有长度属性:
Array.from({length: 10}, (_, i) => i + 1)
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
其他回答
function arrGen(n) {
var a = Array(n)
while (n--) a[n] = n
return a
}
// arrGen(10) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
表演
今天2020.12.11我在Chrome v87、Safari v13.1.2和Firefox v83上对macOS HighSierra 10.13.6进行了测试,以确定所选的解决方案。
后果
适用于所有浏览器
解决方案O(基于while)是最快的(除了Firefox for big N-但在那里很快)解决方案T在Firefox上最快解M,P对于小N很快溶液V(lodash)对于大N是快速的对于小N,溶液W、X是缓慢的溶液F缓慢
细节
我执行两个测试用例:
对于小N=10-您可以在这里运行对于大N=1000000,您可以在此处运行
下面的片段展示了所有测试的解决方案ABCDEFGH我JKLMNOPQRSTU五、W十、
函数A(N){return Array.from({length:N},(_,i)=>i+1)}函数B(N){return Array(N).fill().map((_,i)=>i+1);}函数C(N){return Array(N).jjoin().split(',').map((_,i)=>i+1);}函数D(N){return Array.from(数组(N),(_,i)=>i+1)}函数E(N){return Array.from({length:N},(_,i)=>i+1)}函数F(N){return Array.from({length:N},Number.call,i=>i+1)}函数G(N){return(数组(N)+“”).split(',').map((_,i)=>i+1)}函数H(N){return[…Array(N).keys()].map(i=>i+1);}函数I(N){return[…Array(N).keys()].map(x=>x+1);}函数J(N){return[…数组(N+1).keys()].sslice(1)}函数K(N){return[…Array(N).keys()].map(x=>++x);}函数L(N){let arr;(arr=[…数组(N+1).keys()]).shift();返回arr;}函数M(N){var arr=[];变量i=0;而(N-)arr.push(++i);返回arr;}函数N(N){变量a=[],b=N;而(b-)a[b]=b+1;返回a;}函数O(N){var a=阵列(N),b=0;而(b<N)a[b++]=b;返回a;}函数P(N){var foo=[];对于(var i=1;i<=N;i++)foo.push(i);返回foo;}函数Q(N){对于(var a=[],b=N;b-;a[b]=b+1);返回a;}函数R(N){对于(变量i,a=[i=0];i<N;a[i++]=i);返回a;}函数S(N){设foo,x;对于(foo=[x=N];x;foo[x-1]=x--);返回foo;}函数T(N){返回新的Uint8Array(N).map((item,i)=>i+1);}函数U(N){返回“_”。重复(5)。拆分(“”)。映射((_,i)=>i+1);}函数V(N){返回范围(1,N+1);}函数W(N){return[…(函数*(){让i=0;while(i<N)yield++i})()]}函数X(N){函数序列(最大值,步长=1){返回{[Symbol.iiterat]:函数*(){对于(设i=1;i<=max;i+=步长),得出i}}}返回[…序列(N)];}[A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R、S、T、U、V、W、X]。对于每个(F=>{console.log(`${f.name}${f(5)}`);})<script src=“https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js“integrity=”sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==“crossrorigin=”匿名“></script>此代码段仅显示性能测试中使用的函数-它本身不执行测试!
下面是铬的示例结果
这个问题有很多复杂的答案,但只有一句简单的话:
[...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);
“_”.重复(5).拆分(“”).映射((_,i)=>i+1)将产生[1,2,3,4,5]
试试这个
[…Array.from({length:30}).keys()]