2378

我正在寻找其他方法来创建一个包含1到N的JavaScript数组,其中N只有在运行时才知道。

变量foo=[];对于(var i=1;i<=N;i++){foo.push(i);}

对我来说,我觉得应该有一种不用循环的方法来完成这项工作。

7
  • 413
    在阅读了整个页面后,我得出了这样的结论:您自己的简单for-loop是最简单、可读性最强、最不容易出错的。 评论 2014年5月8日16:09
  • 1
    如果有人需要更高级的东西,我创建了一个node.js库,用于数字、字母、负/正范围等。github.com/jonschlinkert/fill-range。它用于github.com/jonschlinkert/braces用于支撑扩展和github.com/jonschlinkert/micromatch公司用于glob模式 评论 2015年6月9日5:21
  • 另一种方法是:Array.from({length:10},(_,v)=>v) 评论 2019年8月25日0:15
  • @SahilGupta几乎。如果我们想要1到10,我们需要加1,例如:Array.from({length:10},(_,v)=>v+1) 评论 2019年10月13日21:54
  • 不用数组,将foo定义为对象{},然后用foo[i]=i添加自己的索引; 评论 2020年2月27日13:42

80个答案80

重置为默认值
3827

在ES6中使用阵列来自()按键()方法。

Array.from(数组(10).keys())//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

使用的更短版本扩散算子.

[…数组(10).keys()]//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

通过将map函数传递给Array从1开始来自(),带有带有长度属性:

数组.from({长度:10},(_,i)=>i+1)//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
11
  • 136
    只是一个注释,它将始终从0开始。将需要链接地图到数组以调整值([…数组(10).keys()].map(x=>x++);)从1开始 评论 2015年12月29日21:42
  • 80
    只要换一下地图(x=>x++)地图(x=>++x)由于返回值后发生优先增量:)
    – 布洛克
    评论 2016年2月12日9时39分
  • 197
    呃什么!?为什么?地图当你可以简单地?[…数组(N+1).keys()].slice(1)
    – 罗宾
    评论 2016年4月24日19:51
  • 36
    或者不使用钥匙并且只有一张地图->Array.from(数组(10)).map((e,i)=>i+1)
    – 尤纳坦
    评论 2016年6月29日14:03
  • 132
    或者不使用键和映射,只将映射函数传递给 数组.from(数组(10),(e,i)=>i+1) 评论 2017年2月21日13:10
898

您可以这样做:

变量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.7082694901619107,0.9572225909214467,0.8586748542729765,0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588465809822, 0.5577575915958732, 0.16363654541783035]

解释

首先,请注意电话号码(未定义,N)等于数量(N),它只返回N个。我们稍后会用到这个事实。

数组.apply(null,[未定义,未定义,未定])等于数组(未定义、未定义和未定义),它生成一个三元素数组并分配未定义每个元素。

你怎么能把它概括为N个元素?考虑如何数组()效果很好,大致如下:

函数Array(){if(arguments.length==1&&“number”===参数类型[0]&&参数[0]>=0&&参数&&参数[0]<1<<32){返回[…];//长度参数数组[0],由本机代码生成}变量a=[];for(var i=0;i<参数长度;i++){a.push(参数[i]);}返回a;}

自ECMAScript 5以来,Function.prototype.apply(thisArg,argsArray)还接受duck类型的array-like对象作为其第二个参数。如果我们调用数组.apply(null,{长度:N}),然后执行

函数Array(){变量a=[];for(var i=0;i</*参数长度=*/N;i++){a.push(/*参数[i]=*/未定义);}返回a;}

现在我们有了一个N个-元素数组,每个元素设置为未定义.当我们打电话时.map(回调,thisArg)在它上面,每个元素都将被设置为callback.call(thisArg,元素,索引,数组)因此,[未定义,未定义,…,未定义].map(Number.call,Number)将每个元素映射到(Number.call).call(数字,未定义,索引,数组),与Number.call(未定义,索引,数组),正如我们前面所观察到的,其计算结果为指数。这就完成了元素与其索引相同的数组。

为什么要经历数组.apply(null,{长度:N})而不仅仅是阵列(N)? 毕竟,这两个表达式都会产生一个N个-未定义元素的元素数组。不同之处在于,在前一个表达式中,每个元素都是显式的设置设置为未定义,而在后者中,每个元素从未设置。根据文件.map():

回调仅对具有赋值的数组索引调用;对于已删除或从未赋值的索引,不会调用它。

因此,阵列(N)不足;数组(N).map(Number.call,Number)将导致长度数组未初始化N个.

兼容性

由于此技术依赖于函数.prototype.apply()在ECMAScript 5中指定,它将不工作在ECMAScript 5之前的浏览器中,例如Chrome 14和Internet Explorer 9。

13
  • 73
    +1表示聪明,但请注意,这比基本for循环慢几个数量级:jsperf.com/array-magic-vs-for
    – 翘曲术
    评论 2014年1月24日13:59
  • 9
    非常聪明——可能太聪明了。利用这个事实功能.原型.call的第一个参数是要直接映射的对象数组原型.map的迭代器参数对它有一定的影响。 评论 2014年8月17日22:46
  • 18
    这真的非常聪明(近乎滥用JS)。这里真正重要的见解是地图在我看来,是关于未分配的价值观。另一个版本(可能稍显清晰,但较长)是:Array.apply(null,{length:N}).map(function(element,index){return index;}) 评论 2014年10月22日14:23
  • 7
    @BenReich甚至更好(就JS滥用水平而言):Array.apply(null,new Array(N)).map(函数(_,i){return i;})或者,如果是es6和箭头功能,则更短:Array.apply(null,new Array(N)).map((_,i)=>i)
    – 古怪的
    评论 2014年11月25日0:07
  • 2
    如果返回一个从1开始的数组,它实际上会回答OP的问题 评论 2017年5月17日3:59
771

多种方式使用欧洲标准6

使用排列运算符(...)和键方法

[…数组(N).keys()].map(i=>i+1);

填充/映射

数组(N).fill().map((_,i)=>i+1);

阵列起始位置

数组.from(数组(N),(_,i)=>i+1)

数组从和{长度:N}乱劈

数组.from({长度:N},(_,i)=>i+1)

关于广义形式的注释

上述所有形式都可以通过更改生成初始化为几乎任何所需值的数组i+1(输入+1)表达要求(例如。i*2号机组,-我,1+i*2,i%2等)。如果表达式可以由某个函数表示(f)然后第一种形式变得简单

[…数组(N).keys()].map(f)

示例:

数组.from({长度:5},(v,k)=>k+1);// [1,2,3,4,5]

因为数组是用初始化的未定义在每个位置上v(v)未定义

显示所有表单的示例

让演示=(N)=>{控制台日志([…数组(N).keys()].map((i)=>i+1),数组(N).fill().map((_,i)=>i+1),数组.from(数组(N),(_,i)=>i+1),数组.from({长度:N},(_,i)=>i+1))}演示(5)

带有自定义初始化器函数的更通用示例(f)

[…数组(N).keys()].map((i)=>f(i))

甚至更简单

[…数组(N).keys()].map(f)

让演示=(N,f)=>{控制台日志([…数组(N).keys()].map(f),数组(N).fill().map((_,i)=>f(i)),数组.from(数组(N),(_,i)=>f(i)),数组.from({长度:N},(_,i)=>f(i)))}演示(5,i=>2*i+1)

10
  • 6
    对从0开始的数组使用k++ 评论 2017年3月15日1:55
  • 8
    如果要增加,请不要使用k++,使用++k个. 评论 2018年2月13日18:42
  • 5
    小心Array.from在IE中不受支持,除非你是poly填充的。
    – 劳伦
    评论 2018年5月4日21:30
  • 为了让TS编译器满意,可以考虑将未使用的参数替换为lodash:Array.from({length:5},(_,k)=>k+1); 评论 2019年1月29日12:22
  • 1
    @bluejayke我相信自从我发表评论后,这个答案已经被编辑过了,但我特别谈到了数组.from({长度:5},(v,k)=>k+1);,它确实只迭代一次。
    – 威勒德
    评论 2020年6月16日3:57
559

如果我得到了你想要的,你想要一个数字数组1..n个稍后可以循环使用。

如果这就是你所需要的,你可以这样做吗?

var foo=新数组(45);//创建长度为45的空数组

然后,当您想使用它时……(例如,未优化)

for(var i=0;i<foo.length;i++){document.write('项目:'+(i+1)+'的'+foo.length+'<br/>');}

例如,如果您不需要商店数组中的任何内容,您只需要一个长度合适的容器就可以遍历。。。这可能更容易。

在此处查看实际操作:http://jsfiddle.net/3kcvm/

16
  • 7
    你能比我更好地表达我的问题给我留下了深刻的印象,你确实是正确的,因为经过思考,我所需要的只是一组数字,我可以稍后循环:)谢谢你的回答。
    – 戈德斯
    评论 2010年9月19日18:08
  • 196
    @戈德斯:如果这就是你要找的,为什么你需要一个数组?一个简单的var n=45;然后从中循环1..n个就行了。 评论 2010年9月19日18:33
  • 4
    @Godders-要注意,如果您想在创建长度为M的数组后将其大小减小,只需使用foo.length=米---切断信息丢失。在行动中看到它==>jsfiddle.net/ACMXp 评论 2010年9月20日2:11
  • 35
    我真的不明白为什么这个答案甚至有赞成票。。。特别是当OP自己同意这一点时,上面的几句话就毫无意义了,因为他本来可以这么做的变量n=45;.
    – 格子布
    评论 2013年11月4日14:39
  • 112
    @斯库利夫:请注意新阵列(45);不“创建45元素数组”(与[未定义,未定义,..未定义]确实如此)。而是“创建长度为45的空数组”([未定义x 45]),与相同变量foo=[];foo.length=45;.这就是为什么对于每个、和地图将不适用于这种情况。 评论 2014年1月24日14:00
475

阵列天生可以管理其长度。在遍历它们时,它们的索引可以保存在内存中并在此时引用。如果需要知道随机索引索引属于方法。


这就是说,根据您的需要,您可能只需要声明一个特定大小的数组:

var foo=新数组(N);//其中N是正整数/*这将创建一个大小为N的数组,主要用于内存分配,但不创建任何定义的值foo.length//数组大小foo[Math.floor(foo.length/2)]='value'//将值放在数组的中间*/


欧洲标准6

价差

利用扩散算子(...)和钥匙方法,使您能够创建一个大小为N的临时数组来生成索引,然后创建一个可以分配给变量的新数组:

var foo=[…数组(N).keys()];

填充/映射

您可以首先创建所需的数组大小,用未定义的数组填充,然后使用创建一个新数组地图,将每个元素设置为索引。

var foo=数组(N).fill().map((v,i)=>i);

阵列起始位置

这应该初始化为大小为N的长度,并在一次传递中填充数组。

数组.from({length:N},(v,i)=>i)



如果你真的想在上面的例子中获取1..N的值,那么有几个选项可以代替注释和混乱:

  1. 如果索引可用,您可以简单地将其增加一(例如。,++我).
  2. 在不使用索引的情况下,可能是一种更有效的方法,即创建数组,但使N表示N+1,然后从前面移开。

    所以如果你想要100个数字:

    let arr;(arr=[…数组(101).keys()]).shift()




14
  • 我认为,当数字数组用于接收端无法处理的数据时,这很有用。(就像HTML模板只是替换值。) 评论 2012年8月22日15:01
  • 6
    就像我说的,我需要用数字1到10填充下拉列表。这就是全部。有一个用例,我的用例。我就是这样找到这个页面的。因此,手工构建数组比我在这里看到的任何东西都要简单。所以我的要求不是OP的要求。但我有我的答案。
    – 香烟豆
    评论 2018年10月24日11:24
  • 1
    @有一个用例,我也有一个。在有角度的分页中,我想在页脚中显示可单击的页面。因此,我使用*ngFor=“let p of pagesCounter”循环视图中的元素。你有更好的解决方案吗?BTW,结账stackoverflow.com/questions/36354325/… 评论 2019年3月30日8:47
  • 1
    这是错误的。所有示例都会生成形式数组[0,..,n-1]而问题是[1,…,n]
    – 胡赛特
    评论 2020年2月27日13:18
  • 1
    @嘘,是的,你说得对;然而,这就是答案的要点(与所选答案一样),通过在演示文稿中添加1,存储0..N中的数字,并显示1..N+1中的数字 评论 2020年2月27日13:45
217

在ES6中,您可以执行以下操作:

数组(N).fill().map((e,i)=>i+1);

http://jsbin.com/molabiluwa/edit?js,控制台

编辑:改变阵列(45)阵列(N)既然你更新了问题。

控制台.log(数组(45).fill(0).map((e,i)=>i+1));

11
  • 4
    +因为它是一个整体大的O(运行)比肮脏的好.连接.拆分版本-但我仍然认为谦逊的循环更好。
    – 罗宾
    评论 2016年4月24日19:33
  • 4
    constgen=N=>[…(函数*(){设i=0;而(i<N)产生i++})()]
    – 罗宾
    评论 2016年4月24日21:26
  • 1
    您不需要向添加arg.fill()
    – 杰森
    评论 2016年9月30日18:19
  • 9
    我不明白为什么.fill()是必要的。我看到这是在测试节点的repl时,但因为数组(1)[0]==未定义,对fill()的调用有什么区别数组(1).fill(未定义)制造? 评论 2016年10月14日9:45
  • 13
    对于其他感兴趣的人来说,Array(N)和Array(N.fill()之间的区别已经得到了很好的解释在这里 评论 2016年10月17日8:59
126

使用非常流行的底核_.范围法

//_.范围([开始]、停止、[步骤])_.范围(10);//=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]_.范围(1,11);//=>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]_.范围(0,30,5);//=>[0, 5, 10, 15, 20, 25]_.范围(0,-10,-1);//=>[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]_.范围(0);//=>[]
83
功能范围(开始、结束){变量foo=[];for(var i=开始;i<=结束;i++){foo.push(i);}返回foo;}

然后由呼叫

var foo=范围(1,5);

Javascript中没有内置的方法来实现这一点,但如果您需要多次创建它,那么它是一个非常有效的实用函数。

编辑:在我看来,下面是一个更好的范围函数。也许只是因为我对LINQ有偏见,但我认为它在更多情况下更有用。您的里程数可能会有所不同。

功能范围(开始、计数){if(arguments.length==1){计数=开始;开始=0;}var foo=[];for(var i=0;i<计数;i++){foo.push(开始+i);}返回foo;}
7
  • 2
    我喜欢这个。如果您想使用它进行额外的操作,可以将其声明为Array.prototype.range=function(start,end){…};。然后,可以调用任意Array对象上的range(x,y)。 评论 2010年9月19日17:44
  • 9
    宁可让它成为阵列而不是阵列原型因为没有理由(甚至可能被认为相当愚蠢)在每个数组上都有这个方法。
    – ase公司
    评论 2010年9月19日17:47
  • 9
    阵列范围(1,5)可能更合适,但写作有点酷[].范围(1,5).
    – 穆古
    评论 2010年9月19日17:54
  • “宁可让它成为Array的方法,而不是Array.prototype”-有什么区别?你的意思是只在特定数组上?
    – 比劳
    评论 2013年4月11日13:32
  • 4
    @比劳正如亚当斯所说,它看起来很奇怪。如果它在原型上,你可以说foo=[1,2,3];bar=foo.range(0,10);.但那只是。。。令人困惑。bar=数组范围(0,10)更加清晰明确。范围与实例无关,因此没有理由将其作为实例方法。 评论 2013年4月11日14:19
79

简单地说,这对我很管用:

[…数组(5)].map(…)
7
  • 14
    […数组(5)].map((x,i)=>i)
    – 吉姆101
    评论 2023年4月3日1:13
  • 2
    优雅而简单。 评论 2023年4月20日5:15
  • 1
    @jimm101我很好奇为什么[…数组(5)].map((a)=>7)给出了7个数组,而数组(5).map((a)=>7)没有。使用...仍在生成一个未定义值的数组,为什么会有不同? 评论 2023年10月6日19:01
  • @KonradViltersten解构产生一个未定义的数组,另一个产生一个空值数组。未定义表示已创建元素,但未赋值,因此索引仍然有效。
    – 吉姆101
    评论 2023年10月8日14:13
  • @jimm101谢谢你的回复。我感到困惑的是我不依赖索引这里,就这个项目(无论是空的、空的还是其他什么)。你是说我们实际上没有为空的价值观?因为如果我们是这样的话,我想7以在存在空值时放置在每个点中。帮助我理解。 评论 2023年10月8日14:41
77

性能

今天2020.12.11,我在Chrome v87、Safari v13.1.2和Firefox v83上对macOS HighSierra 10.13.6进行了测试,以获得选定的解决方案。

结果

适用于所有浏览器

  • 解决方案O(运行)(基于虽然)是最快的(除了Firefox的big N,但它在那里很快)
  • 解决方案T在Firefox上实现big N最快
  • 解决方案M、P对于小N来说很快
  • 解决方案V(lodash)对于大N是快速的
  • 对于较小的N,溶液W、X速度较慢
  • 溶液F缓慢

在此处输入图像描述

细节

我执行了2个测试用例:

下面的片段介绍了所有测试的解决方案A类 B类 C类 D类 E类 F类 G公司 H(H) J型 K(K) L(左) M(M) N个 O(运行) P(P) R(右) S公司 T型 U型 V(V) W公司 X(X)

功能A(N){return Array.from({length:N},(_,i)=>i+1)}功能B(N){return数组(N).fill().map((_,i)=>i+1);}功能C(N){return数组(N).join().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[…数组(N).keys()].map(i=>i+1);}功能I(N){return[…数组(N).keys()].map(x=>x+1);}函数J(N){return[…数组(N+1).keys()].slice(1)}函数K(N){return[…数组(N).keys()].map(x=>+x);}函数L(N){let arr;(arr=[…数组(N+1).keys()]).shift();返回arr;}函数M(N){var arr=[];var 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){变量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){对于(var 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){return new Uint8Array(N).map((item,i)=>i+1);}功能U(N){return“_”.repeat(5).split(“”).map((_,i)=>i+1);}功能V(N){返回_范围(1,N+1);}函数W(N){return[…(函数*(){设i=0;而(i<N)yield++i})()]}函数X(N){功能序列(最大,步长=1){返回{[Symbol.iterator]:函数*(){对于(设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=>{控制台.log(`${f.name}${f(5)}`);})
<script src=“https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js“integrity=”sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovwww==“crossorigin=”anonymous“></script>此代码段仅显示性能测试中使用的函数-它本身不执行测试!

下面是铬的示例结果

在此处输入图像描述

1
  • 对于那些关心性能的人来说:创建阵列所需的时间只是故事的一半。您还应该关注使用之后的数组可能会有所不同,这取决于数组的构造方式,因为引擎具有不同的内部表示对于密集阵列和稀疏阵列(aka带“洞”的阵列),稀疏阵列将保留“稀疏阵列”表示,即使它在构造后变得密集。如果有疑问,请在实际用例中进行基准测试。
    – kaya3型
    评论 2022年8月14日12:52
64

最快的填充方法阵列在v8中是:

[…数组(5)].map((_,i)=>i);

结果是:[0, 1, 2, 3, 4]

56

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

[…数组(255).keys()].map(x=>x+1)

此外,尽管上面写得很短(而且很简洁),但我认为下面写得快一些(对于最大长度:

127,国际8,

255,单位8,

32767、国际16,

65535,单位16,

2147483647,国际32,

4294967295,Uint32。

(基于最大整数值),还有更多类型化数组):

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

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

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

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

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

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


因此,有了上述功能,上述超低速“简单的单线”就变成了超快速、均匀的短线:

范围(114000);
5
48

使用ES2015/ES6排列运算符

[…数组(10)].map((_,i)=>i+1)

console.log([…数组(10)].map((_,i)=>i+1))

1
  • 最后,我要找的是,我还要指定1为起点
    – 8千磅
    评论 2022年9月6日23:50
45

您可以使用:

new Array(/*所需的任意数字*/).joon().split(',').map(函数(项,索引){return++索引;})

例如

新阵列(10).joon().split(',').map(函数(项,索引){return++索引;})

将创建以下数组:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 还有,为什么不呢new Array(10).join().split(',').map(function(){return++参数[1]});?
    – 用户2039981
    评论 2016年1月3日20:31
  • 1
    @在某些情况下,带有内部参数的Murplyx函数不会被JS引擎优化(即使对于V8也是如此,请参阅jsperf.com/arguments-vs-array-argument/2) 评论 2016年1月5日21:25
  • 4
    这是一个有趣的解决方案,但它完全不切实际——必须解析数组3次(一次到参加,一次到分裂,而一旦你真正想做的事情)就不太好了-我知道他们似乎因为某些原因而失宠了,但简单地使用一种好的老式风格要好得多!
    – 罗宾
    评论 2016年4月24日19:29
45

空数组和数组中只有数字的解决方案

const-arrayOne=新数组(10);console.log(arrayOne);const数组Two=[…数组(10).keys()];console.log(arrayTwo);var arrayThree=数组.from(数组(10).keys());console.log(arrayThree);const arrayStartWithOne=Array.from(Array(10).keys(),item=>item+1);console.log(arrayStartWithOne)

0
42

如果你碰巧使用d3.js型在你的应用程序中,D3为你提供了一个帮助函数。

因此,要获得从0到4的数组,非常简单:

d3.范围(5)[0, 1, 2, 3, 4]

并按照您的请求获取1到5的数组:

d3.范围(1,5+1)[1, 2, 3, 4, 5]

结账本教程了解更多信息。

1
  • 这条评论让我有了抬头看的想法range()函数在RamdaJS中,它恰好是我在当前项目中使用的JS库。很 完美。
    – 变形的
    评论 2015年12月24日5:34
40

这可能是生成数字数组的最快方法

最短的

变量a=[],b=N;而(b--)a[b]=b+1;

内联

var arr=(函数(a,b){while(a-)b[a]=a;return b})(10,[]);//arr=[0,1,2,3,4,5,6,7,8,9]

如果要从1开始

var arr=(函数(a,b){while(a-)b[a]=a+1;返回b})(10,[]);//arr=[1,2,3,4,5,6,7,8,9,10]

想要功能吗?

函数范围(a,b,c){c=[];而(a-)c[a]=a+b;返回c}//长度,开始,占位符var arr=范围(10.5);//arr=[5,6,7,8,9,10,11,12,13,14]

为什么?

  1. 虽然是最快的环路

  2. 直接设置比

  3. []比…快新阵列(10)

  4. 它很短。。。看第一个代码。然后看看这里的所有其他函数。

如果你喜欢,就不能没有对于

对于(var a=[],b=7;b>0;a[--b]=b+1)//a=[1,2,3,4,5,6,7]

对于(var a=[],b=7;b---;a[b]=b+1)//a=[1,2,3,4,5,6,7]
17
  • 8
    最好用基准来支持这些说法。尝试jsperf.com网站. 评论 2013年8月21日13:58
  • 哈哈,请马特,因为你不喜欢我的答案,别再投票给我的其他人了。。。stackoverflow.com/a/18344296/2450730…使用console.time()或其调用方式。。。不是jsperf。 评论 2013年8月21日14:00
  • 4
    仅供参考:正如John Reisig几年前首次发布的那样,在某些平台(即windows:P)上,时间每16ms向浏览器反馈一次。在多任务环境中测量执行时间也存在其他问题。jsperf.com已经实现了运行测试,以便它们在统计上是正确的。可以跑步了控制台.time()为了获得直觉,但为了证明,您需要jsperf.com,它会显示其他人(不同硬件等)的跨浏览器结果
    – 诺格图
    评论 2013年9月14日8:58
  • @但这是不正确的:变量a=[],b=N;而(b--){a[b]=a+1}; 评论 2015年5月15日23:28
  • 6
    @球菌-虽然不是总是比其他环路更快。在某些浏览器中,递减while循环比for循环慢得多,您不能这样概括javascript的性能,因为有太多不同优化的实现。然而,总的来说,我喜欢你的方法。;-)
    – 罗布·G
    评论 2015年8月9日23:57
39

如果你正在使用lodash,你可以使用_.范围:

_.范围([start=0],end,[step=1])

创建数字数组(积极和/或消极)从开始到,但不是包括,结束。如果指定负启动,则使用步骤-1没有终点或台阶。如果未指定结束,则将其设置为开始使用start,然后设置为0。

示例:

_范围(4);// ➜ [0, 1, 2, 3]_范围(-4);// ➜ [0, -1, -2, -3]_.范围(1,5);// ➜ [1, 2, 3, 4]_.范围(0、20、5);// ➜ [0, 5, 10, 15]_.范围(0,-4,-1);// ➜ [0, -1, -2, -3]_.范围(1,4,0);// ➜ [1, 1, 1]_.范围(0);// ➜ []
1
36

填充的新方法阵列是:

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

结果是:[0, 1, 2, 3, 4]

2
  • 1
    这是一个很好的答案,虽然从技术上来说,这个问题来自1-N,而不是0-(N-1) 评论 2019年3月10日3:41
  • 也许我们可以使用rest操作符(…),比如const[,…array]=array(5).keys();
    – 钻石
    评论 2021年3月11日12:16
34

使用ES6,您可以:

//`n`是要初始化数组的大小//“null”是数组将填充的内容(可以是任何其他值)数组(n).fill(null)
1
  • 由于数组的值实际上是使用此解决方案填充的,地图对于每个将起作用。 评论 2019年11月22日8:32
31

非常简单,易于精确生成1-N

const[,…result]=数组(11).keys();console.log('Result:',Result);

30

最终总结报告。。Drruummm辊-

这是最短代码生成大小为N的数组(此处为10)不使用ES6.科科上面的版本很接近,但不是最短的。

(函数(n){for(a=[];n--;a[n]=n+1);返回a})(10)

但是无可争议的胜利者这个代码高尔夫球(用最少字节的源代码解决特定问题的竞赛)是尼科·鲁塔萨拉宁.使用数组构造函数和ES6排列运算符.(大多数ES6语法是有效的typeScript,但以下语法不是。所以在使用时要谨慎)

[…数组(10).keys()]
6
  • 这不是0-10吗?[…数组(10).keys()]
    – 格雷格
    评论 2016年5月25日18:19
  • Webstorm建议(new Array(10)).keys(),对吗?
    – 家伙
    评论 2016年7月15日9:09
  • (new Array(10)).keys(),返回ArrayIterator{},而不是数组
    – 萨皮
    评论 2016年7月15日19:34
  • 这将创建一个全局变量。循环应为对于(var a=[];n--;a[n]=n+1)
    – 库比
    评论 2016年8月4日17:09
  • 你错过了代码高尔夫球(用最少字节的源代码解决特定问题的竞赛)答案中的一部分:)
    – 萨皮
    评论 2016年8月4日17:33
30

https://stackoverflow.com/a/49577331/8784402

使用Delta

对于javascript

最小和单线
[…数组(N)].map((v,i)=>来自+i*步骤);

示例和其他备选方案

Array.from(Array(10).keys()).map(i=>4+i*2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22][…数组(10).keys()].map(i=>4+i*-2);//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]数组(10).fill(0).map((v,i)=>4+i*2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]数组(10).fill().map((v,i)=>4+i*-2);//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14][…数组(10)].map((v,i)=>4+i*2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Range函数
常数范围=(从、到、步进)=>[…数组(数学地板((到-从)/步)+1)].map((_,i)=>从+i*步);范围(0、9、2);//=> [0, 2, 4, 6, 8]//也可以将范围函数指定为Array类中的静态方法(但不推荐)数组范围=(从,到,步长)=>[…数组(数学地板((到-从)/步)+1)].map((_,i)=>从+i*步);阵列范围(2,10,2);//=> [2, 4, 6, 8, 10]数组范围(0,10,1);//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]数组范围(2,10,-1);//=> []数组范围(3,0,-1);//=> [3, 2, 1, 0]
作为Iterators
类别范围{构造函数(总数=0,步骤=1,从=0开始){this[Symbol.iterator]=函数*(){for(设i=0;i<total;+i++*step的产量){}};}}[…新范围(5)];//五大要素//=> [0, 1, 2, 3, 4][…新范围(5,2)];//第二步五要素//=> [0, 2, 4, 6, 8][…新范围(5,-2,10)];//五要素,从10开始第2步//=>[10, 8, 6, 4, 2][…新范围(5,-2,-10)];//五元素与步骤-2从-10//=> [-10, -12, -14, -16, -18]//也可与for配合使用。。循环的对于新范围(5,-2,10)的(i)console.log(i);// 10 8 6 4 2
仅作为发电机
常量范围=函数*(总计=0,步长=1,从=0开始){for(设i=0;i<total;+i++*step的产量){}};数组起始(范围(5,-2,-10));//=> [-10, -12, -14, -16, -18][…范围(5,-2,-10)];//五要素,从-10开始第2步//=> [-10, -12, -14, -16, -18]//也可与for配合使用。。循环的对于(范围(5,-2,10)的i)控制台.log(i);// 10 8 6 4 2//懒惰的加载方式const number0toInf=范围(无限);number0toInf.next().value;//=> 0number0toInf.next().value;//=> 1// ...

从-到-带阶梯/增量

使用迭代器
类别范围2{构造函数(to=0,step=1,from=0){this[Symbol.iterator]=函数*(){设i=0,长度=数学地板(从上到下)/台阶)+1;而(i<长度)从+i++*步产生;};}}[…新范围2(5)];//前5个整数//=> [0, 1, 2, 3, 4, 5][…新范围2(5,2)];//使用步骤2从0到5//=> [0, 2, 4][…新范围2(5,-2,10)];//从10到5,步骤-2//=> [10, 8, 6]
使用生成器
const Range2=函数*(to=0,step=1,from=0){设i=0,长度=数学地板(从上到下)/台阶)+1;而(i<长度)从+i++*步产生;};[…范围2(5,-2,10)];//从10到5,步骤-2//=> [10, 8, 6]设even4to10=范围2(10,2,4);even4到10.next().value;//=> 4even4到10.next().value;//=> 6even4到10.next().value;//=> 8even4到10.next().value;//=> 10even4到10.next().value;//=>未定义

对于Typescript

class _Array扩展了Array{静态范围(从:数字,到:数字,步骤:数字):数字[]{return Array.from(Array(Math.floor(to-from)/step)+1).map((v,k)=>从+k*步);}}_数组范围(0,9,1);
0
26

快速

这个解决方案可能是最快的,它的灵感来自lodash _.range函数(但my更简单、更快)

设N=10,i=0,a=数组(N);而(i<N)a[i++]=i;控制台.log(a);

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

  • 内存在开始时分配一次a=阵列(N)
  • 递增指数我++使用-看起来比递减索引快30%左右我--(可能是因为CPU正向缓存内存更快)

这个答案

1
  • 然而阵列(N)构造函数创建了一个带有“holes”的数组,当以后实际使用时,该数组的性能可能会降低。引擎对数组使用不同的内部表示,这取决于数组中的内容以及它们是否有“洞”;如果创建了孔,则内部表示可以降级,但如果删除了所有孔,则不会升级。用V8的术语来说,此解决方案创建了一个孔_SMI_构件数组,其中打包_SMI_ELEMENTS最好是数组。v8.dev/blog/elements-kinds#元素-kind-latticeV8开发人员的建议是使用相反。
    – kaya3型
    评论 2022年8月14日12:46
24

ES6中还有另一种方法,使用阵列起始位置它有两个参数,第一个是arrayLike(在本例中是一个带有长度属性),第二个是映射函数(在本例中,我们将项映射到其索引)

数组.from({长度:10},(v,i)=>i)

这是较短的,可以用于其他序列,如生成偶数

数组.from({length:10},(v,i)=>i*2)

此外,这比大多数其他方法都有更好的性能,因为它只在阵列中循环一次。检查狙击手进行一些比较

//打开开发控制台以查看结果计数=100000console.time(“来自对象”)for(设i=0;i<count;i++){range=数组。from({length:10},(v,i)=>i)}console.timeEnd(“来自对象”)控制台.time(“从键”)for(设i=0;i<count;i++){range=Array.from(数组(10).keys())}console.timeEnd(“从键”)控制台.time(“应用”)for(设i=0;i<count;i++){range=Array.apply(null,{length:10}).map(函数(元素,索引){return index;})}console.timeEnd(“应用”)

2
20

使用新的Array方法和=>ES6标准的函数语法(在编写时仅限于Firefox)。

通过用未定义:

数组(N).fill().map((_,i)=>i+1);

阵列起始位置把“洞”变成未定义所以阵列地图按预期工作:

数组.from(数组(5)).map((_,i)=>i+1)
4
  • 8
    同样,您也可以在ES6中执行以下操作:数组.from({length:N},(v,k)=>k). 评论 2015年6月8日9:19
  • 首选Xappli的方法:Array.from是为几乎完全相同的场景创建的,它意味着一个映射回调。这是一个很好的解决方案,可以解决希望在类似数组的对象上使用Array方法的一般问题,而无需使用诸如数组.prototype.map.call,例如,对于从返回的NodeLists文档.query选择或全部.developer.mozilla.org/en/docs/Web/JavaScript/Reference/… 评论 2015年10月16日2:50
  • 我将此与下划线范围语法进行权衡,范围读起来更好。 评论 2015年11月6日5:13
  • 从技术上讲不是阵列起始位置将稀疏值转换为未定义值。相反阵列(5)被称为arguments对象,该对象反过来将稀疏值解释为未定义的值:) 评论 2016年10月22日11:21
20

在ES6中:

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

或者更好(没有额外的变量,也没有额外的呼叫):

数组.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(){返回参数[1]+1});

或者,在ES5中,对于map函数(如阵列起始位置上述ES6中的函数),您可以使用Number.call

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

或者,如果你反对.切片在这里,您还可以执行上述ES5等效操作(从ES6),如:

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

数组(…数组(9)).map((_,i)=>i);console.log(数组(…数组(9)).map((_,i)=>i))

1
15
对于(var i,a=[i=0];i<10;a[i++]=i);

a=[1,2,3,4,5,6,7,8,9,10]

0
14

似乎唯一没有出现在这个相当完整的答案列表中的味道是一个具有生成器的味道;因此,为了纠正这一点:

constgen=N=>[…(函数*(){设i=0;而(i<N)产生i++})()]

可以这样使用:

第(4)代//[0,1,2,3]

这件事的好处是你不需要增加。。。要从@igor-shubin给出的答案中获得灵感,您可以很容易地创建一系列随机数:

常数gen=N=>[…(函数*(){设i=0;而(i++<N)生成Math.random()})()]

而不是什么冗长的运营成本高,如:

const-slow=N=>new数组(N).join().split(',').map((e,i)=>i*5)// [0,5,10,15,...]

你可以这样做:

const-fast=N=>[…(函数*(){设i=0;而(i++<N)产生i*5})()]

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.