创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]
为什么?
-
while
最快的循环 -
直接设置比
push
更快 -
[]
比new Array(10)
-
它很短…看第一个代码。 然后看看这里的所有其他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]
注 : apply
, map
, join
– split
…. 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
这有点复杂,但也很酷。