如何创建包含1… N的数组

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

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

对我来说,感觉应该有一种方法可以在没有循环的情况下做到这一点。

2000115 次浏览

试试这个:

var foo = [1, 2, 3, 4, 5];

如果您使用的是脚本编写,您可以通过以下操作创建一个范围:

var foo = [1..5];

否则,如果您使用vanilla JavaScript,如果您想将数组初始化为可变长度,则必须使用循环。

function range(start, end) {var foo = [];for (var i = start; i <= end; i++) {foo.push(i);}return foo;}

然后被召唤

var foo = range(1, 5);

在Javascript中没有内置的方法可以做到这一点,但如果您需要多次执行此操作,它是一个完全有效的实用函数。

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

function range(start, count) {if(arguments.length == 1) {count = start;start = 0;}
var foo = [];for (var i = 0; i < count; i++) {foo.push(start + i);}return foo;}

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

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

var foo = new Array(45); // create an empty array with length 45

然后当你想使用它时…(未优化,仅举个例子)

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

例如,如果你不需要商店数组中的任何东西,你只需要一个可以迭代的合适长度的容器……这可能更容易。

点击这里查看:http://jsfiddle.net/3kcvm/

数组固有地管理它们的长度。当它们被遍历时,它们的索引可以保存在内存中并在该点引用。如果需要知道随机索引,可以使用indexOf方法。


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

var foo = new Array(N);   // where N is a positive integer
/* this will create an array of size, N, primarily for memory allocation,but does not create any defined values
foo.length                                // size of Arrayfoo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array*/


ES6

传播

使用扩展运算符(...)和keys方法,您可以创建一个大小为N的临时数组来生成索引,然后创建一个可以分配给您的变量的新数组:

var foo = [ ...Array(N).keys() ];

填写/地图

你可以先创建你需要的数组的大小,用untex填充它,然后使用map创建一个新数组,它将每个元素设置为索引。

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

Array.from

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

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



为了代替注释和混淆,如果您真的想在上面的示例中捕获1… N中的值,有几个选项:

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

    如果你想要100个数字:

    let arr; (arr=[ ...Array(101).keys() ]).shift()




只是为了好玩,我想从伊恩·亨利的回答开始构建。

当然,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 1if (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 endfor (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是项目:12中的1
-7.5是项目:2 of 12
-16是项目:3 of 12
-24.5是项目:4 of 12
-33是项目:12中的5
-41.5是项目:12中的6
-50是项目:12中的7
-58.5是项目:12中的8
-67是项目:12中的9
-75.5是项目:10 of 12
-84是项目:12中的11
-92.5是项目:12 of 12

jsFiddle例子

此函数使用自动生成的#0数组。

该函数创建一个数组,其中填充了从start开始到end结束的值,增量大小为increment,其中

range(start, end, increment);

每个值都有一个默认值,增量的符号无关紧要,因为增量的方向取决于start和end的相对大小。

我一直在寻找一个功能的解决方案,我最终得到了:

function numbers(min, max) {return Array(max-min+2).join().split(',').map(function(e, i) { return min+i; });}
console.log(numbers(1, 9));

注意:join().split(',')将稀疏数组转换为连续数组。

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

查看本教程以获取更多信息。

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

最短

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,placeholdervar arr=range(10,5);//arr=[5,6,7,8,9,10,11,12,13,14]

为啥?

  1. while是最快的循环

  2. 直接设置比push

  3. []new Array(10)

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

如果你喜欢不能没有进行

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

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

以下函数返回一个填充有数字的数组:

var createArrayOfNumbers = function (n) {return Array.apply(null, new Array(n)).map(function (empty, index) {return index;});};

请注意,使用数组构造函数创建的数组由孔组成,因此不能使用map等数组函数遍历它。因此使用Array.apply函数。

你可以这样做:

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.7082694901619107,0.9572225909214467,0.8586748542729765,08653848143294454,0008339877473190427,09911756622605026,08133423360995948,08377588465809822,05577575915958732,016363654541783035]

补充说明

首先,注意Number.call(undefined, N)等价于Number(N),它只返回N。我们稍后会使用这个事实。

Array.apply(null, [undefined, undefined, undefined])等效于Array(undefined, undefined, undefined),它产生一个三元素数组并将undefined分配给每个元素。

你如何将其推广到N元素?考虑#0是如何工作的,它是这样的:

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 5Function.prototype.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。当我们对其调用#1时,每个元素都将设置为callback.call(thisArg, element, index, array)的结果。因此,[undefined, undefined, …, undefined].map(Number.call, Number)将把每个元素映射到(Number.call).call(Number, undefined, index, array),这与Number.call(undefined, index, array)相同,正如我们之前观察到的,其计算结果为index。这完成了元素与其索引相同的数组。

为什么要经历Array.apply(null, {length: N})而不仅仅是Array(N)的麻烦?毕竟,这两个表达式都将产生一个由未定义元素组成的N元素数组。不同之处在于,在前一个表达式中,每个元素都显式地到未定义,而在后者中,每个元素都从未设置。根据#2的留档:

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

因此,Array(N)是不够的;Array(N).map(Number.call, Number)将导致长度为N的未初始化数组。

兼容性

由于此技术依赖于ECMAScript 5中指定的Function.prototype.apply()行为,因此在ECMAScript 5之前的浏览器(如Chrome14和Internet Explorer 9)中它将不工作

在上面即兴:

var range = function (n) {return Array(n).join().split(',').map(function(e, i) { return i; });}

可以获得以下选项:

1)Array.initv

var arrayInitTo = function (n,v) {return Array(n).join().split(',').map(function() { return v; });};

2)获取反向范围:

var rangeRev = function (n) {return Array(n).join().split(',').map(function() { return n--; });};

有一个小函数,它允许使用像[1,2]. range(3,4)->[1,2,3,4]也适用于负参数。享受。

Array.prototype.range = function(from, to){var range = (!to)? from : Math.abs(to - from) + 1, increase = from < to;var tmp = Array.apply(this, {"length": range}).map(function(){return (increase)?from++ : from--;}, Number);
return this.concat(tmp);};

你可以使用这个:

new Array(/*any number which you want*/).join().split(',').map(function(item, index){ return ++index;})

例如

new Array(10).join().split(',').map(function(item, index){ return ++index;})

将创建以下数组:

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

以获得在min, max之间具有n个随机数的数组(虽然不是唯一的)

function callItWhatYouWant(n, min, max) {return Array.apply(null, {length: n}).map(Function.call, function(){return Math.floor(Math.random()*(max-min+1)+min)})}

使用非常流行的下划线_. range方法

// _.range([start], stop, [step])
_.range(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]_.range(1, 11); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]_.range(0, 30, 5); // => [0, 5, 10, 15, 20, 25]_.range(0, -10, -1); //  => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]_.range(0); // => []

对于小范围,切片很好。N仅在运行时已知,因此:

[0, 1, 2, 3, 4, 5].slice(0, N+1)

所有这些都太复杂了。只需:

function count(num) {var arr = [];var i = 0;
while (num--) {arr.push(i++);}
return arr;}
console.log(count(9))//=> [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]

或者做一个从ab的范围

function range(a, b) {var arr = [];
while (a < b + 1) {arr.push(a++);}
return arr;}
console.log(range(4, 9))//=> [ 4, 5, 6, 7, 8, 9 ]

我没有看到任何基于递归函数的解决方案(我自己也从未写过递归函数),所以这是我的尝试。

请注意,array.push(某物)返回数组的新长度:

(a=[]).push(a.push(a.push(0))) //  a = [0, 1, 2]

使用递归函数:

var a = (function f(s,e,a,n){return ((n?n:n=s)>e)?a:f(s,e,a?a:a=[],a.push(n)+s)})(start,end) // e.g., start = 1, end = 5

编辑:另外两种解决方案

var a = Object.keys(new Int8Array(6)).map(Number).slice(1)

var a = []var i=setInterval(function(){a.length===5?clearInterval(i):a.push(a.length+1)})

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

undefined填充孔:

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

Array.from将“洞”变成undefined,因此Array.map按预期工作:

Array.from(Array(5)).map((_, i) => i + 1)

比字符串变体简单一点:

// create range by NArray(N).join(0).split(0);
// create a range starting with 0 as the valueArray(7).join(0).split(0).map((v, i) => i + 1) // [1, 2, 3, 4, 5, 6, 7]

更新(1/4/2018):已更新以解决确切的OP问题。感谢@less less拨打这个电话!

在ES6中使用Array#0#1方法。

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#0,其中包含具有length属性的对象:

Array.from({length: 10}, (_, i) => i + 1)//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

让我们分享我的:p

Math.pow(2, 10).toString(2).split('').slice(1).map((_,j) => ++j)

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

function range(n) {let a = Array(n);for (let i = 0; i < n; a[i++] = i);return a;}
Array(8).fill(0).map(Number.call, Number)

窃取IgorsNumber.call技巧,但使用fill()略微缩短。仅适用于ES6及以上。

在ES6中,您可以:

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

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

编辑:将Array(45)更改为Array(N),因为您已经更新了问题。

console.log(Array(45).fill(0).map((e,i)=>i+1));

Array.prototype.fill()

a = Object.keys( [].fill.call({length:7}, '' ) ).map(Number)a.pop();console.debug(a)

[0,1,2,3,4,5,6]

Object.keys(Array.apply(0, Array(3))).map(Number)

返回[0, 1, 2]。与伊戈尔·舒宾的精彩回答非常相似,但诡计略少(并且长一个字符)。

说明:

  • Array(3) // [undefined × 3]生成一个长度为n=3的数组。不幸的是,这个数组对我们几乎没有用,所以我们必须…
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined]使数组可迭代。注意:null更常用于应用的第一个arg,但0更短。
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']然后获取数组的键(工作是因为数组是类型数组是一个具有键索引的对象。
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]并映射键,将字符串转换为数字。

使用es6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);

最终总结报告… Drrruummm Rolll-

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

(function(n){for(a=[];n--;a[n]=n+1);return a})(10)

但是这个代码高尔夫的无可争议的赢家(用最少字节的源代码解决特定问题的竞争)是Niko Ruotsalainen。使用Array Constructor和ES6扩散算子。(ES6的大部分语法都是有效的typeScript,但以下不是。所以在使用它时要明智)

[...Array(10).keys()]

在ES6中还有另一种方法,使用Array.from接受2个参数,第一个是arraylike(在本例中是具有length属性的对象),第二个是映射函数(在本例中我们将项目映射到其索引)

Array.from({length:10}, (v,i) => i)

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

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

这也比大多数其他方法具有更好的性能,因为它只在数组中循环一次。检查代码片段以进行一些比较

// open the dev console to see results
count = 100000
console.time("from object")for (let i = 0; i<count; i++) {range = Array.from({length:10}, (v,i) => i )}console.timeEnd("from object")
console.time("from keys")for (let i =0; i<count; i++) {range = Array.from(Array(10).keys())}console.timeEnd("from keys")
console.time("apply")for (let i = 0; i<count; i++) {range = Array.apply(null, { length: 10 }).map(function(element, index) { return index; })}console.timeEnd("apply")

我可以生成的最少代码:

for(foo=[x=100]; x; foo[x-1]=x--);console.log(foo);

似乎目前在这个相当完整的答案列表中唯一没有的味道是一个具有生成器的答案;所以为了补救:

const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]

它可以这样使用:

gen(4) // [0,1,2,3]

这样做的好处是,你不需要增加……要从@igor-Shubin给出的答案中获得灵感,你可以很容易地创建一个random数组:

const gen = N => [...(function*(){let i=0;while(i++<N) yield Math.random()})()]

而不是漫长操作上昂贵的东西,比如:

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

你可以这样做:

const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]

使用ES6的多种方法

使用扩展运算符(...)和键方法

[ ...Array(N).keys() ].map( i => i+1);

填写/地图

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

Array.from

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

Array.from和{ length: N } hack

Array.from({ length: N }, (_, i) => i+1)

关于广义形式的注记

上述所有形式都可以通过将i+1更改为所需的表达式(例如i*2-i1+i*2i%2等)来生成初始化为几乎任何期望值的数组。如果表达式可以由某个函数f表示,那么第一种形式变得简单

[ ...Array(N).keys() ].map(f)

示例:

Array.from({length: 5}, (v, k) => k+1);// [1,2,3,4,5]

由于数组在每个位置上初始化为undefined,因此v的值将为undefined

示例展示所有表单

let demo= (N) => {console.log([ ...Array(N).keys() ].map(( i) => i+1),Array(N).fill().map((_, i) => i+1) ,Array.from(Array(N), (_, i) => i+1),Array.from({ length: N }, (_, i) => i+1))}
demo(5)

带有自定义初始化函数f的更通用示例,即。

[ ...Array(N).keys() ].map((i) => f(i))

甚至更简单

[ ...Array(N).keys() ].map(f)

let demo= (N,f) => {console.log([ ...Array(N).keys() ].map(f),Array(N).fill().map((_, i) => f(i)) ,Array.from(Array(N), (_, i) => f(i)),Array.from({ length: N }, (_, i) => f(i)))}
demo(5, i=>2*i+1)

如果你使用的是Lodash,你可以使用_范围

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

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

示例:

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

您可以使用函数生成器或函数*表达式。这里是[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function]和对函数生成器链接的引用[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function]。

let a = 1, b = 10;

函数*范围(a, b){对于(var i=a; i<=b;++i)产生i;

Array.from(range(a, b));// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

[...range(a, b)]// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

尝试向Number的原型添加迭代器

Number.prototype[Symbol.iterator] = function *(){let i = 0;while(i < this) yield i++;return;}

现在数字是可迭代的,只需将一个数字传递给Array.from

Array.from(10);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

或者其他任何需要可迭代的地方,例如对于…循环

for(const number of 10) console.log(number);//logs 0 through 9 sequentially

这有点复杂,但也很酷。

使用ES2015/ES6扩展运算符

[...Array(10)].map((_, i) => i + 1)

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

for(var i,a=[i=0];i<10;a[i++]=i);

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

function arrGen(n) {var a = Array(n)while (n--) a[n] = nreturn a}// arrGen(10) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

嗯,简单但重要的问题。函数式JS在Array对象下肯定缺乏通用的展开方法,因为我们可能需要创建一个数字项数组,不仅是简单的[1,2,3,...,111],而且是由函数产生的系列,可能像x => x*2而不是x => x

目前,要执行此工作,我们必须依赖Array.prototype.map()方法。然而,为了使用Array.prototype.map(),我们需要提前知道数组的大小。仍然…如果我们不知道大小,那么我们可以使用Array.prototype.reduce(),但是Array.prototype.reduce()旨在减少(折叠)而不是展开…?

所以很明显我们需要一个Array.unfold()工具在函数式JS中。这是我们可以简单地实现自己的东西,就像;

Array.unfold = function(p,f,t,s){var res = [],runner = v =>  p(v,res.length-1,res) ? [] : (res.push(f(v)),runner(t(v)), res);return runner(s);};

Arrays.unfold(p,f,t,v)需要4个参数。

  • p这是一个定义停止位置的函数。p函数像许多数组函数一样接受3个参数。值、索引和当前结果数组。它将返回一个布尔值。当它返回true时,递归迭代停止。
  • f这是一个返回下一个项目函数值的函数。
  • t这是一个返回下一个参数的函数,在下一回合中提供给f
  • <的trong>的是种子值,将用于通过f计算索引0的舒适座位。

因此,如果我们打算创建一个包含1,4,9,16,25…n^2这样的序列的数组,我们可以简单地做like。

Array.unfold = function(p,f,t,s){var res = [],runner = v =>  p(v,res.length-1,res) ? [] : (res.push(f(v)),runner(t(v)), res);return runner(s);};
var myArr = Array.unfold((_,i) => i >= 9, x => Math.pow(x,2), x => x+1, 1);console.log(myArr);

ES6版本。

通过使用#0第二个可选参数:

Array.from(arraylike[, mapFn[, thisArg]])

我们可以从空的Array(10)位置构建编号数组:

Array.from(Array(10), (_, i) => i)

var arr = Array.from(Array(10), (_, i) => i);document.write(arr);

对我来说,这是一个更有用的工具:

/*** create an array filled with integer numbers from base to length* @param {number} from* @param {number} to* @param {number} increment* @param {Array} exclude* @return {Array}*/export const count = (from = 0, to = 1, increment = 1, exclude = []) => {const array = [];for (let i = from; i <= to; i += increment) !exclude.includes(i) && array.push(i);return array;};

可迭代版本使用不修改Number.prototype发生器函数。

function sequence(max, step = 1) {return {[Symbol.iterator]: function* () {for (let i = 1; i <= max; i += step) yield i}}}
console.log([...sequence(10)])

我发现了这个旧的线程,因为我自己也在想同样的事情,但我想这里没有一个答案比你原来的例子更容易,正如科科多科评论的那样,哈哈!

最后我自己使用了这个方法:

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)可能更快。

ES5版本,效率低下,但也许是最短的表达式,而不是声明,其中变量填充了例如。for循环:

(Array(N)+'').split(',').map(function(d,i){return i})

// A solution where you do not allocate a N sized array (ES6, with some flow annotation):function* zeroToN(N /* : number */)/* : Generator<number, void, empty> */ {for (let n = 0; n <= N; n += 1) yield n;}
// With this generation, you can have your arrayconsole.log([...zeroToN(10-1)])
// but let's define a helper iterator functionfunction mapIterator(iterator, mapping) {const arr = [];for (let result = iterator.next(); !result.done; result = iterator.next()) {arr.push(mapping(result.value));}return arr;}
// now you have a map function, without allocating that 0...N-1 array
console.log(mapIterator(zeroToN(10-1), n => n*n));

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

[...Array(5)].map((_,i) => i);

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

填充Array的新方法是:

const array = [...Array(5).keys()]console.log(array)

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

'_'.repeat(5).split('').map((_, i) => i + 1)将产生[1, 2, 3, 4, 5]

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

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

还有,虽然上面写的很短(也很整洁),但我觉得下面写的快一点(最大长度为:

127, int8,

255, Uint8,

32,767, Int16,

65,535, Uint16,

2,147,483,647, Int32,

4,294,967,295,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”;

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

function range(min, max) {min = min && min.constructor == Number ? min : 0;!(max && max.constructor == Number && max > min) && // boolean statements can also be used with void return types, like a one-line if statement.((max = min) & (min = 0));  //if there is a "max" argument specified, then first check if its a number and if its graeter than min: if so, stay the same; if not, then consider it as if there is no "max" in the first place, and "max" becomes "min" (and min becomes 0 by default)
for(var i = 0, arr = new (max < 128 ? Int8Array :max < 256 ? Uint8Array :max < 32768 ? Int16Array :max < 65536 ? Uint16Array :max < 2147483648 ? Int32Array :max < 4294967296 ? Uint32Array :Array)(max - min); i < arr.length; i++) arr[i] = i + min;return arr;}


//and you can loop through it easily using array methods if you wantrange(1,11).forEach(x => console.log(x));
//or if you're used to pythons `for...in` you can do a similar thing with `for...of` if you want the individual values:for(i of range(2020,2025)) console.log(i);
//or if you really want to use `for..in`, you can, but then you will only be accessing the keys:
for(k in range(25,30)) console.log(k);
console.log(range(1,128).constructor.name,range(200).constructor.name,range(400,900).constructor.name,range(33333).constructor.name,range(823, 100000).constructor.name,range(10,4) // when the "min" argument is greater than the "max", then it just considers it as if there is no "max", and the new max becomes "min", and "min" becomes 0, as if "max" was never even written);


因此,有了上述功能,上述超慢速的“简单单行程序”就变得超级快,甚至更短:

range(1,14000);

您可以使用Es6中的数组填充和映射;就像一些人在回答这个问题时建议的那样。下面是一些例子:

Example-One: Array(10).fill(0).map((e,i)=>i+1)
Result-One: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Example-Two: Array(100/10).fill(0).map((e,i)=>(i*10)+10)
Result-Two:[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

我更喜欢这样,因为我发现它很简单,也很容易。

使用递归的ES6解决方案。不同于所有其他解决方案

const range = (n, A = []) => (n === 1) ? [n, ...A] : range(n - 1, [n, ...A]);

console.log(range(5));

这是摘要(在控制台中运行):

// setup:var n = 10000000;function* rangeIter(a, b) {for (let i = a; i <= b; ++i) yield i;}function range(n) {let a = []for (; n--; a[n] = n);return a;}function sequence(max, step = 1) {return {[Symbol.iterator]: function* () {for (let i = 1; i <= max; i += step) yield i}}}
var t0, t1, arr;// testst0 = performance.now();arr = Array.from({ length: n }, (a, i) => 1)t1 = performance.now();console.log("Array.from({ length: n }, (a, i) => 1) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = range(n);t1 = performance.now();console.log("range(n) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = Array.from(rangeIter(0, n));t1 = performance.now();console.log("Array.from(rangeIter(0, n)) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = [...rangeIter(0, n)];t1 = performance.now();console.log("[...rangeIter(0, n)] Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = Array.from(sequence(n));t1 = performance.now();console.log("Array.from(sequence(n)) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = [...sequence(n)];t1 = performance.now();console.log("[...sequence(n)] Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = Array(n).fill(0).map(Number.call, Number);t1 = performance.now();console.log("Array(n).fill(0).map(Number.call, Number) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = Array.from(Array(n).keys());t1 = performance.now();console.log("Array.from(Array(n).keys()) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();arr = [...Array(n).keys()];t1 = performance.now();console.log("[...Array(n).keys()] Took " + (t1 - t0) + " milliseconds.");

最快的是数组(n).填充(0). map(Number.call, Number),第二个是[…数组(n). key()]

但是'… rangeIter'方式非常方便(可以内联),快速且更强大

由于有很多好的答案,这也可能是一个选项,您还可以使用下面的函数创建一个函数,它将适用于任何数字组合

const start = 10;const end = 30;const difference = Math.abs(start-end);const rangeArray = new Array(difference + 1).fill(undefined).map((val, key) => {return start > end ? start - key : start + key;})

使用ES6,您可以:

// `n` is the size you want to initialize your array// `null` is what the array will be filled with (can be any other value)Array(n).fill(null)

试试这个

const foo = numberOfItems=> [...Array(numberOfItems).keys()].map(i => i+1);

Array(...Array(9)).map((_, i) => i);
console.log(Array(...Array(9)).map((_, i) => i))

Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));

来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

基于高投票的答案和高投票的评论。

const range = (from, to) => [...Array(to + 1).keys()].slice(from);
// usagelet test = [];test = range(5, 10);console.log(test); // output: [ 5, 6, 7, 8, 9, 10 ]

在ES6中:

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

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

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)

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

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

var foo = Array.from(Array(N), (v, i) => i + 1);

我会这样做使用#0

var foo = [...Array(5).keys()].map(foo => foo + 1)
console.log(foo)

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

与德尔塔

对于javascript

最小和单线
[...Array(N)].map((v, i) => from + i * step);

示例和其他替代方案

Array.from(Array(10).keys()).map(i => 4 + i * 2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
[...Array(10).keys()].map(i => 4 + i * -2);//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
Array(10).fill(0).map((v, i) => 4 + i * 2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Array(10).fill().map((v, i) => 4 + i * -2);//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
[...Array(10)].map((v, i) => 4 + i * 2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
范围函数
const range = (from, to, step) =>[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
range(0, 9, 2);//=> [0, 2, 4, 6, 8]
// can also assign range function as static method in Array class (but not recommended )Array.range = (from, to, step) =>[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
Array.range(2, 10, 2);//=> [2, 4, 6, 8, 10]
Array.range(0, 10, 1);//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Array.range(2, 10, -1);//=> []
Array.range(3, 0, -1);//=> [3, 2, 1, 0]
作为迭代器
class Range {constructor(total = 0, step = 1, from = 0) {this[Symbol.iterator] = function* () {for (let i = 0; i < total; yield from + i++ * step) {}};}}
[...new Range(5)]; // Five Elements//=> [0, 1, 2, 3, 4][...new Range(5, 2)]; // Five Elements With Step 2//=> [0, 2, 4, 6, 8][...new Range(5, -2, 10)]; // Five Elements With Step -2 From 10//=>[10, 8, 6, 4, 2][...new Range(5, -2, -10)]; // Five Elements With Step -2 From -10//=> [-10, -12, -14, -16, -18]
// Also works with for..of loopfor (i of new Range(5, -2, 10)) console.log(i);// 10 8 6 4 2
仅作为发电机
const Range = function* (total = 0, step = 1, from = 0) {for (let i = 0; i < total; yield from + i++ * step) {}};
Array.from(Range(5, -2, -10));//=> [-10, -12, -14, -16, -18]
[...Range(5, -2, -10)]; // Five Elements With Step -2 From -10//=> [-10, -12, -14, -16, -18]
// Also works with for..of loopfor (i of Range(5, -2, 10)) console.log(i);// 10 8 6 4 2
// Lazy loaded wayconst number0toInf = Range(Infinity);number0toInf.next().value;//=> 0number0toInf.next().value;//=> 1// ...

从到带步骤/增量

使用迭代器
class Range2 {constructor(to = 0, step = 1, from = 0) {this[Symbol.iterator] = function* () {let i = 0,length = Math.floor((to - from) / step) + 1;while (i < length) yield from + i++ * step;};}}[...new Range2(5)]; // First 5 Whole Numbers//=> [0, 1, 2, 3, 4, 5]
[...new Range2(5, 2)]; // From 0 to 5 with step 2//=> [0, 2, 4]
[...new Range2(5, -2, 10)]; // From 10 to 5 with step -2//=> [10, 8, 6]
使用发电机
const Range2 = function* (to = 0, step = 1, from = 0) {let i = 0,length = Math.floor((to - from) / step) + 1;while (i < length) yield from + i++ * step;};
[...Range2(5, -2, 10)]; // From 10 to 5 with step -2//=> [10, 8, 6]
let even4to10 = Range2(10, 2, 4);even4to10.next().value;//=> 4even4to10.next().value;//=> 6even4to10.next().value;//=> 8even4to10.next().value;//=> 10even4to10.next().value;//=> undefined

对于TypeScript

class _Array<T> extends Array<T> {static range(from: number, to: number, step: number): number[] {return Array.from(Array(Math.floor((to - from) / step) + 1)).map((v, k) => from + k * step);}}_Array.range(0, 9, 1);

否用于在ES6解决方案中创建数组

js no for 100数组

1. padStart

// string arrconst arr = [...``.padStart(100, ` `)].map((item, i) => i + 1 + ``);
// (100) ["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", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100"]

// number arrconst arr = [...``.padStart(100, ` `)].map((item, i) => i + 1);
// (100) [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, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

2.类型化数组

Uint8Array

// number arrconst arr = new Uint8Array(100).map((item, i) => i + 1);
// Uint8Array(100) [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, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
// string arrconst arr = [...new Uint8Array(100).map((item, i) => i + 1)].map((item, i) => i + 1 + ``);
// (100) ["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", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100"]

快速

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

let N=10, i=0, a=Array(N);
while(i<N) a[i++]=i;


console.log(a);

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

  • 内存在开始时由a=Array(N)分配一次
  • 使用递增索引i++-看起来比递减索引i--快30%左右(可能是因为CPU缓存在向前方向上更快)

这个答案中进行了20多种其他解决方案的速度测试

性能

今天2020.12.11我在macOS HighSierra 10.13.6上对Chromev87、Safariv13.1.2和Firefox v83进行了测试。

搜索结果

对于所有浏览器

  • 解决方案O(基于while)是最快的(除了Firefox的大N-但它很快)
  • 解决方案T在Firefox上对于大N最快
  • 解M,P对于小N是快的
  • 对于大N,解V(Lodash)很快
  • 解W, X对于小N是慢的
  • 解F慢

在此处输入图片描述

详情

我执行两个测试用例:

  • 对于小N=10-你可以运行它这里
  • 对于大N=1000000-你可以运行它这里

下面的代码片段展示了所有经过测试的解决方案ABCDEFGHIJKLMNOPQRSTUVWX

function A(N) {return Array.from({length: N}, (_, i) => i + 1)}
function B(N) {return Array(N).fill().map((_, i) => i+1);}
function C(N) {return Array(N).join().split(',').map((_, i) => i+1 );}
function D(N) {return Array.from(Array(N), (_, i) => i+1)}
function E(N) {return Array.from({ length: N }, (_, i) => i+1)}
function F(N) {return Array.from({length:N}, Number.call, i => i + 1)}
function G(N) {return (Array(N)+'').split(',').map((_,i)=> i+1)}
function H(N) {return [ ...Array(N).keys() ].map( i => i+1);}
function I(N) {return [...Array(N).keys()].map(x => x + 1);}
function J(N) {return [...Array(N+1).keys()].slice(1)}
function K(N) {return [...Array(N).keys()].map(x => ++x);}
function L(N) {let arr; (arr=[ ...Array(N+1).keys() ]).shift();return arr;}
function M(N) {var arr = [];var i = 0;
while (N--) arr.push(++i);
return arr;}
function N(N) {var a=[],b=N;while(b--)a[b]=b+1;return a;}
function O(N) {var a=Array(N),b=0;while(b<N) a[b++]=b;return a;}
function P(N) {var foo = [];for (var i = 1; i <= N; i++) foo.push(i);return foo;}
function Q(N) {for(var a=[],b=N;b--;a[b]=b+1);return a;}
function R(N) {for(var i,a=[i=0];i<N;a[i++]=i);return a;}
function S(N) {let foo,x;for(foo=[x=N]; x; foo[x-1]=x--);return foo;}
function T(N) {return new Uint8Array(N).map((item, i) => i + 1);}
function U(N) {return '_'.repeat(5).split('').map((_, i) => i + 1);}
function V(N) {return _.range(1, N+1);}
function W(N) {return [...(function*(){let i=0;while(i<N)yield ++i})()]}
function X(N) {function sequence(max, step = 1) {return {[Symbol.iterator]: function* () {for (let i = 1; i <= max; i += step) yield i}}}
return [...sequence(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].forEach(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==" crossorigin="anonymous"> </script>  
This snippet only presents functions used in performance tests - it does not perform tests itself!

以下是chrome的示例结果

在此处输入图片描述

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

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

你可以这样做:

var arr = Array.from(Array(10).keys())arr.shift()console.log(arr)

试试这个吧

[...Array.from({length:30}).keys()]

从1开始:

[...Array(31).keys()].map(a=>a+1)

可以使用Int8ArrayInt16ArrayInt32Array创建一个范围从1到n的数组,如下所示:

const zeroTo100 = new Int8Array(100).map((curr, index) => curr = index + 1);/* Int8Array(100) [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, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,93, 94, 95, 96, 97, 98, 99, 100]

您还可以使用以下类型化数组在数组内生成1到n个项目。

  1. Uint8Array, Uint16Array, Uint32Array, Uint8Array, Uint16Array, Uint16Array, Uint32Array, Uint16Array, Uint16Array, Uint16Array, Uint16Array, Uint16Array, Uint16Array, Uint16Array, Uint16Array, Uint16Array,
  2. 大数据矩阵BigInt64Array
  3. Uint8ClampeArray中文版
  4. FloatArray64、FloatArray32、FloatArray64的逻辑关系

当然,除了数字之外,你失去了在这些数组中放置任何东西的能力,所以使用这个小快捷方式是有风险的。

此外,如果你只需要一个包含n个零的数组,那么只需这样做:

const arr_100_0s = new Int8Array(100)

编辑:您可以使用它来快速生成一个范围,如下所示:

function range(start, end) {const arr = new Int8Array(end - start + 1).map((curr, i) => curr + i + start);return arr;}
range(15, 30); // Int8Array(16) [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]

不完全是用户要求的,但在IMO中高度相关。

感谢他/她的回答@陈志立。我在我的实用程序中写了这个:

const range = ({from = 0, to, step = 1, length = Math.ceil((to - from) / step)}) =>Array.from({length}, (_, i) => from + i * step)

例子:

const range = ({from = 0, to, step = 1, length = Math.ceil((to - from) / step)}) =>Array.from({length}, (_, i) => from + i * step)
console.log(range({length: 5}), // [0, 1, 2, 3, 4]range({to: 5}),    // [0, 1, 2, 3, 4]range({from: 2, to: 5}),    // [2, 3, 4] (inclusive `from`, exclusive `to`)range({from: 2, length: 4}), // [2, 3, 4, 5]range({from: 1, to: 5, step: 2}), // [1, 3]range({from: 1, to: 6, step: 2}), // [1, 3, 5])

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

const arrayOne = new Array(10);console.log(arrayOne);
const arrayTwo = [...Array(10).keys()];console.log(arrayTwo);
var arrayThree = Array.from(Array(10).keys());console.log(arrayThree);
const arrayStartWithOne = Array.from(Array(10).keys(), item => item + 1);console.log(arrayStartWithOne)

我能想到的最简洁的:

[...''.padEnd(N)].map((_,i)=>i+1)

简单量程发生器:

    const min = 2000;const max = 2022;const range = Array.from({ length: max - min + 1 }, (v, k) => k + min);console.log('range', range);

✅简单地说,这对我有效:

[...new Array(5)].map(...)