创build一个包含1 … N的JavaScript数组

我正在寻找下面的任何替代方法来创build一个包含1到N的JavaScript数组,其中N只在运行时被知道。

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

对我来说,感觉就像没有循环一样,应该有这样做的方法。

如果我得到你以后的东西,你想要一个数组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/

你可以这样做:

 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.95752225909214467,0.85386714542729765,0.8653848143294454,0.008339877473190427,0.99911756622605026,0.8133423360995948,0.8377588465809822,0.5577575915958732,0.167653654541783035]

说明

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

Array.apply(null, [undefined, undefined, undefined])相当于Array(undefined, undefined, undefined) ,它产生一个三元素的数组,并为每个元素赋值undefined

你怎么能把它推广到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.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 。 当我们调用.map(callback, thisArg)时,每个元素将被设置为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) ? 毕竟,这两个expression式都会导致一个未定义元素的N元素数组。 不同之处在于,在前一个expression式中,每个元素被明确地设置为未定义的,而在后者中,每个元素从未被设置。 根据.map()的文档:

只对已经赋值的数组的索引调用callback 。 对于已被删除或从未被赋值的索引,不会调用它。

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

兼容性

由于此技术依赖于ECMAScript 5中指定的Function.prototype.apply()行为,因此它不适用于ECMAScript 5之前的浏览器,如Chrome 14和Internet Explorer 9。

在ES6中使用Array ()和keys()方法。

 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] 

在ES6中,你可以这样做:

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

http://jsbin.com/molabiluwa/edit?js,console

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

使用非常stream行的Underscore _.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); // => [] 

简单和简单的方法:

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

因此:

  Array.from({length: N}, (v, k) => k+1); // [1,2,3,...,N] 
 const range = (N) => Array.from({length: N}, (v, k) => k+1) ; console.log( range(5) ) 
 function range(start, end) { var foo = []; for (var i = start; i <= end; i++) { foo.push(i); } return foo; } 

然后通过

 var foo = range(1, 5); 

在Javascript中没有内置的方法,但是如果你需要多次创build,这是一个非常有效的实用函数。

编辑:在我看来,以下是一个更好的范围function。 也许只是因为我被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; } 

你可以使用这个:

 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;}) 

将创build以下数组:

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

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

看看这个教程了解更多信息。

我知道你的问题是要求在数组中填充数组,但我不确定你为什么要这样做。

数组天生的pipe理自己的长度。 当它们被遍历时,它们的索引可以被保存在内存中并且被引用。 如果需要知道随机索引,则可以使用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 Array foo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array */ 

ES6

传播

利用spread运算符( ... )和keys方法,可以创build一个大小为N的临时数组来生成索引,然后创build一个可以分配给variables的新数组:

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

填充/地图

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

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

这是生成一组数字的最快方式

最短

 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?

 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] 

为什么?

  1. while最快的循环

  2. 直接设置比push更快

  3. []new Array(10)

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

如果你喜欢不能没有的话

 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] 

applymapjoinsplit …. srsly ??? 这该死的慢!!!!!!和兼容性?

使用ES2015 / ES6扩展运算符

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

最终总结报告Drrruummm Rolll –

这是在不使用ES6的情况下生成大小为N的数组(这里是10)的最短代码 。 Cocco的版本接近但不是最短的。

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

但是,这个Code高尔夫球无可争议的胜利者是Niko Ruotsalainen (竞争解决源代码字节数最less的特定问题)。 使用数组构造函数和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) 

而且这比大多数其他方式具有更好的性能,因为它只在数组中循环一次。 检查snippit进行一些比较

 // 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") 

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

undefined填充孔:

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

Array.from将“洞”变成undefined所以Array.map按预期工作:

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

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

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

创build从开始到结束(但不包括结束)的一系列数字(正数和/或负数)。 如果没有结束或步骤指定负开始,则使用-1的步长。 如果未指定end,则将其设置为以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); // ➜ [] 

尝试这个:

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

如果您正在使用CoffeeScript ,则可以通过执行以下操作来创build范围:

 var foo = [1..5]; 

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

我正在寻找一个function的解决scheme,我最终:

 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(',')将稀疏数组转换为一个连续的数组。

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

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

请注意,使用数组构造函数创build的数组由孔组成,因此无法使用像map这样的数组函数遍历数组。 因此使用Array.apply函数。

比string变体稍微简单一些:

 // create range by N Array(N).join(0).split(0); // create a range starting with 0 as the value Array(7).join(0).split(0).map(Number.call, Number); // [0, 1, 2, 3, 4, 5, 6] 

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

返回[0, 1, 2] 。 非常类似于伊戈尔·舒宾的优秀答案 ,但稍微less一些(和一个字符更长)。

说明:

  • Array(3) // [undefined × 3]生成一个长度为n = 3的数组。 不幸的是,这个arrays对我们来说几乎是无用的,所以我们必须…
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined]使数组成为可迭代的。 注意:null更常见于应用的第一个arg,但是0的更短。
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']然后得到数组的键(因为数组是typeof数组是一个对象索引的键。
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]并映射到键上,将string转换为数字。

我没有看到任何基于recursion函数的解决scheme(并且从来没有写过recursion函数),所以这里是我的尝试。

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

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

并用recursion函数:

 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) // eg, start = 1, end = 5 

编辑:另外两个解决scheme

 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)}) 
 for(var i,a=[i=0];i<10;a[i++]=i); 

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

只是另一个ES6版本。

通过使用Array.from第二个可选参数:

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

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

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

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

即兴即兴:

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

可以得到以下选项:

1)Array.init为值v

 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--; }); }; 
 Array(8).fill(0).map(Number.call, Number) 

窃取Igors Number.call绝招但用fill()稍微缩短。 只适用于ES6及以上。

您可以使用函数发生器或函数*expression式。 这里是[ 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;

function* range(a, b) { for (var i = a; i <= b; ++i) yield 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]

让我们分享一下我的

 var i = 10; Math.pow(2, i).toString(2).split('').map((i,j) => j) 

使用ES6

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

尝试添加一个迭代器到数字的原型。

 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 

这有点复杂,但也很酷。