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


1161

我正在寻找以下所有替代方法,以创建一个包含1到N的JavaScript数组,其中N仅在运行时才知道。

var foo = [];

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

在我看来,应该有一种没有循环的方法。


224
阅读了整页之后,我得出的结论是,您自己的简单for循环是最简单,最易读且最不容易出错的。
Kokodoko 2014年

如果有人需要更高级的内容,我创建了一个node.js库,用于处理数字,字母,负/正范围等。github.com / jonschlinkert / fill-range。它在github.com/jonschlinkert/braces中用于括号扩展,在github.com/jonschlinkert/micromatch中用于全局模式
jonschlinkert

1
您应该编辑说“如何创建长度为N的数组”,而不是“ ...包含1 ... N”,后者表示将存在值从1到N的元素
史蒂文·兰多

7
@StevenLandow为什么OP应该重命名?他想要一个带有值的数组1 ... N吗?
安德烈·埃里科

好问题,好标题,(有点)愚蠢的答案。
Bitterblue

Answers:


381

如果我能得到想要的结果,则需要一个数字数组,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/


4
令您印象深刻的是,您设法比我更好地表达了我的问题,您的观点确实正确,因为反思时,我所需要的只是一个数字数组,我可以稍后循环查看:)谢谢您的回答。
Godders 2010年

147
@Godders:如果这是您要寻找的,为什么需要数组?一个简单的var n = 45;然后循环1..n就可以了。
卡萨布兰卡

3
@Godders-注意,如果要在创建数组长度为M后减小数组的大小,只需使用foo.length = M---截止信息将丢失。观看操作==> jsfiddle.net/ACMXp
Peter Ajtai 2010年

24
我真的不明白为什么这个答案甚至会被否决...尤其是当OP自己同意时,在上面的一些评论中这没有任何意义,因为他本可以做到的var n = 45;
plalx

72
@scunliffe:请注意,这new Array(45);不会“创建45个元素的数组”(含义与之相同[undefined,undefined,..undefined])。而是“与创建长度为45的空数组”([undefined x 45])相同var foo = []; foo.length=45;。这就是原因forEach,并且map在这种情况下将不适用。
tomalec 2014年

1307

在ES6中,使用Array from()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]

74
请注意,该值始终从0开始。需要将a链接map到数组以调整值([...Array(10).keys()].map(x => x++);),以从1开始
Sterling Archer

32
只是由于优先级的变化而改变map(x => x++)map(x => ++x)因为返回值之后会发生:)
Brock

92
what !!为什么map当您可以简单地slice[...Array(N+1).keys()].slice(1)
罗宾

19
或不使用keys,只有一张地图->Array.from(Array(10)).map((e,i)=>i+1)
yonatanmn

60
或不使用按键和地图,只需将地图函数传递给from Array.from(Array(10), (e,i)=>i+1)
Fabio Antunes,2017年

844

您可以这样做:

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、0.8653848143294454、0.008339877473190427、0.9911756622605026、0.8133423360995948、0.8377588465809822、0.5577575915958732、0.16363654541783035]

说明

首先,请注意Number.call(undefined, N)等于Number(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)?毕竟,这两个表达式都将导致一个由N个元素组成的未定义元素数组。不同之处在于,在前一个表达式中,每个元素都显式设置为undefined,而在后一个表达式中,从未设置每个元素。根据以下文档.map()

callback仅针对已分配值的数组索引调用;对于已删除或从未分配值的索引,不会调用它。

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

兼容性

由于此技术依赖Function.prototype.apply()于ECMAScript 5 中指定的行为,因此在ECMAScript 5 之前的浏览器(例如Chrome 14和Internet Explorer 9)中将无法使用


62
+1表示聪明,但请注意,这比循环的原始速度慢了几个数量级:jsperf.com/array-magic-vs-for
warpech 2014年

7
非常聪明-可能也是。利用的Function.prototype.call第一个参数是this直接在Array.prototype.map迭代器参数上进行映射的对象这一事实具有一定的精髓。
2014年

14
这真的非常聪明(在滥用JS时会感到厌烦)。map我认为,这里真正重要的见解是对未分配值的特质。另一个版本(可能更长一些,但可能更清晰)是: Array.apply(null, { length: N }).map(function(element, index) { return index; })
Ben Reich 2014年

6
@BenReich更好(就JS滥用水平而言):Array.apply(null, new Array(N)).map(function(_,i) { return i; }) 或者,对于es6和arrow函数,甚至更短: Array.apply(null, new Array(N)).map((_,i) => i)
奇怪的是,2014年

1
如果返回一个以1开始的数组,它实际上会回答OP的问题
Hai Phan

478

使用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 }黑客

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

展示所有表格的示例

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

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

甚至更简单

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


33

5
使用k ++表示从0开始的数组
Borgboy

1
如果要增加,请不要使用k++,请使用++k
亚历克斯

4
IE中不支持Array.from,除非您要对其进行多填充。
劳伦(Lauren)'18年

2
为了使TS编译器满意,请考虑使用lodash替换未使用的参数:Array.from({length:5},(_,k)=> k + 1);
Journeycorner

296

数组天生地管理它们的长度。在遍历它们时,它们的索引可以保存在内存中并在那一点被引用。如果需要知道随机索引,则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

传播

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

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

填充/贴图

您可以先创建所需数组的大小,将其填充为undefined,然后使用创建一个新数组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()





我相信这在将数字数组用于无法在接收端处理的数据时很有用。(就像只是替换值的HTML模板一样。)
Neil Monroe

为什么有人要这样做,是要有一个数字数组来填充一个下拉列表,为用户提供1到10的选择。手工制作一个小的数组[1,2,3 ... 10]有意义,但是如果是1到50?如果结束号码更改怎么办?
CigarDoug

@CigarDoug我毫不怀疑有一个用例,但是我猜它很小。为什么需要一个数字数组,通常在一个数组上进行迭代时,索引将被用作循环结构的一部分(可以作为循环主体函数的参数,也可以作为计数器变量),因此保存数字数组似乎并不重要只是创建一个指定宽度的数组,或者只是一个保存数组上限的变量。我可以想到一些用例,但是OP并没有表达这些用例
vol7ron

4
就像我说的,我需要用数字1到10填充一个下拉列表。有一个用例,我的用例。这就是我找到此页面的方式。因此,只需要手工构建一个数组就比我在这里看到的要简单。因此,我的要求不是OP的要求。但是我有我的答案。
CigarDoug

1
@ vol7ron有一个用例,我也有一个。在角形,分页中,我要显示页脚中可单击的页面。因此,我使用* ngFor =“ pagesCounter的let p”在视图中循环元素。您对此有更好的解决方案吗?顺便说一句,请查看stackoverflow.com/questions/36354325/…–
达利博

186

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


3
1,因为它是一个整体的Ø比讨厌的更好.join.split版本-但我仍然认为不起眼的循环更好。
罗宾

我同意@Robin-除了算法复杂性之外,谦虚循环始终更具可读性。但是,随着Java中lambda的出现,我认为map它将很快成为此类事情的标准。
Nate

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

8
我不明白为什么.fill()有必要。我看到是在对节点的repl进行测试时,但是由于Array(1)[0] === undefined,对Array(1).fill(undefined)make中的fill()的调用有何不同?
多米尼克

11
对于其他感兴趣的人,在这里
Dominic


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

2
我喜欢这个。如果您想花更多的精力,可以将其声明为Array.prototype.range = function(start,end){...};。然后,您可以在任何Array对象上调用range(x,y)。
扎克·拉特纳

8
而是使它的方法Array,而不是Array.prototype因为没有任何理由(甚至可能会被认为是相当愚蠢的)有每个数组此方法。
亚当斯2010年

9
Array.range(1, 5)可能会更合适,但是写作有点酷[].range(1, 5)
MooGoo 2010年

“而是使它成为Array而不是Array.prototype的方法”-有什么区别?您是说仅在特定阵列上?
pilau 2013年

3
就像亚当斯说的那样,@ pilau看起来很奇怪。如果是在原型上,您可以说foo = [1, 2, 3]; bar = foo.range(0, 10);。但这只是...令人困惑。bar = Array.range(0, 10)更清晰明了。该范围与实例无关,因此没有理由使其成为实例方法。
伊恩·亨利

53

填写Arrayv8 的最快方法是:

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

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


有没有一种方法无需额外的变量_
bluejayke19,2016年

@bluejayke no :(
–dydykyі19年

苛刻,您知道.map的源代码是什么吗?我不知道,如果它比任何一个for循环快,但如果不是那么理论上我们只要defineProperty,使一个新的
bluejayke

49

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

[...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。

(基于最大整数值),还有更多关于Typed Arrays的信息

(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 want
range(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);

@JVG但不是为了更快的功能?
bluejayke

非常正确。每个人都在寻找这种简单的班轮!
supersan

@supersan虽然它超级慢:)
bluejayke

使用新fill方法的现代javascript :Array(255).fill(0,0,255)
cacoder

@cacoder有多快,它创建了多少个数组以及有多少次迭代?
bluejayke19年

42

您可以使用此:

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]

另外,为什么不new Array(10).join().split(',').map(function() {return ++arguments[1]});呢?
超级

1
@Murplyx对于某些情况下的参数内将JS引擎未优化功能(真正的甚至是V8,见jsperf.com/arguments-vs-array-argument/2
nktssh

4
这是一个有趣的解决方案,但这是完全不切实际的-不得不将数组解析3次(一次join,一次split,到一次,以及一次您实际要执行的操作)不是很好-我知道它们似乎已经失宠了出于某种原因,但是简单地使用一个好的老式循环会更好!
罗宾

42

ES6可以达到目的:

[...Array(12).keys()]

查看结果:

[...Array(12).keys()].map(number => console.log(number))


5
实际上,他们要求的是1..N,而不是0..N-1
YakovL

1
是的,[...Array(N + 1).keys()].slice(1)将产生1..N
David G

由于某种原因,该解决方案在Expo(本机)应用程序的正式版中不起作用。[...Array(N + 1).keys()]这段代码返回一个空数组,但是只是在生产模式下,使用开发模式才有效。
FabianoLothor

3
.keys()答案已经给出年前,有500多个upvotes。您的答案有什么好处?
Dan Dascalescu

39

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

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


此注释使我有了在RamdaJS中查找range()函数的想法,该函数恰好是我在当前项目中使用的JS库。完善。
morphatic


38

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

最短的

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,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. 简短...看第一个代码。然后在这里查看所有其他功能。

如果你喜欢生活中不可缺少

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]

8
最好用基准来支持这些要求。尝试jsperf.com
马特·鲍尔

2
大声笑jsperf ...请马特只是因为你不喜欢我的答案停止投票我的其他人... stackoverflow.com/a/18344296/2450730 ...使用console.time()或如何称呼...不是jsperf 。
2013年

4
仅供参考:正如约翰·赖西格(John Reisig)几年前首次发表的那样-在某些平台上(意味着Windows:P),每16毫秒就会向浏览器提供一次时间。在多任务环境中,测量执行时间还存在其他问题。jsperf.com已经实施了运行测试,以便在统计上正确。console.time()可以凭直觉来运行,但是作为证明,您需要jsperf.com,它显示了其他人(不同硬件等)的跨浏览器结果
naugtur

3
@cocco,这是不正确的:var a=[],b=N;while(b--){a[b]=a+1};
vintagexav 2015年

5
@cocco- 虽然并不总是比其他循环快。在某些浏览器中,递减的while循环比for循环要慢得多,您不能像这样对javascript性能做出一般性的陈述,因为有许多实现有许多不同的优化。但是,总的来说,我喜欢您的方法。;-)
RobG 2015年

32

填充的新方法Array是:

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

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


这是一个非常好的答案,尽管从技术上讲问题是来自1-N,而不是0-(N-1)
bluejayke

31

如果使用lodash,则可以使用_.range

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

创建从开始到结束但不包括结束的数字数组(正数和/或负数)。如果指定了负开始而没有结束或步长,则使用-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);
// ➜ []

30

使用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)

由于数组的值实际上是使用此解决方案填充的,map因此forEach可以正常工作。
dontmentionthebackup

26

最终摘要报告.. Drrruummm Rolll-

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

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

但是,这场Code Golf 的无可争议的获胜者(解决源代码最少字节中的特定问题的竞争者)是Niko Ruotsalainen。使用数组构造器和ES6传播算符。(大多数ES6语法是有效的typeScript,但以下语法不是有效的。因此,在使用它时应谨慎对待)

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

为什么要投下反对票?长长的答案列表很难遵循,因此想到了总结。
sapy 2016年

这不是0-10吗?[... Array(10).keys()]
格雷格

Webstorm建议(new Array(10))。keys(),对吗?
盖伊

(new Array(10))。keys(),返回ArrayIterator {},而不是数组
2016年

这将创建一个全局变量a。循环应为for(var a=[];n--;a[n]=n+1)
kube

20

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


嘿,这很整洁,我喜欢它。但是,它不会返回OP期望的结果。为此,它必须写为Array.from({length:N}, (v,i) => i+1)
CervEd 16'Oct

这些neato hack仍然比旧的for loop慢5-10倍
Dan Dascalescu

16

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

通过填充孔undefined

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

Array.from轮流“孔”进入undefined这样Array.map按预期工作:

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

7
同样的,你也可以做ES6如下:Array.from({length: N}, (v, k) => k)
XåpplI'-I0llwlg'I -

Xappli的方法更为可取:Array.from几乎是在这种情况下创建的,它暗示了映射回调。对于要在类似数组的对象上使用Array方法而无需求助于诸如的复杂方法Array.prototype.map.call(例如,对于从返回的NodeLists而言),这是一个很好的解决方案document.querySelectorAlldeveloper.mozilla.org/en/docs/Web/JavaScript/Reference/...
乔希从Qaribou

我正在权衡下划线范围语法和范围读取更好。
ooolala 2015年

从技术上讲,不是Array.from这样会将稀疏值变成未定义。而是Array(5)将其称为参数对象,该对象又会将稀疏值解释为未定义值:)
CervEd



10

只是另一个ES6版本。

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

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

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

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

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


这比更为复杂,且速度约慢10倍[...Array(11).keys()].slice(1)
Dan Dascalescu

10

似乎,在这个相当完整的答案列表中,当前唯一没有出现的风味是具有生成器的风味。因此要补救:

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

可以这样使用:

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

这样做的好处是,您不必增加就可以...为了从@ igor-shubin提供的答案中汲取灵感,您可以非常轻松地创建随机数组:

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})()]

10

您可以使用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]

我更喜欢这样做,因为我发现它简单直接。



10

在ES6中:

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

ES5:

Array.apply(0, {length: 1000}).map(function(x,i){return i});

9

使用ES6

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

谢谢!我认为这是最优雅的答案!Array.from(Array(n))如果不支持传播运算符,也可以使用。
阿米特(Amit)

最初我不知道为什么要使用散布运算符,但是后来我map在MDN上阅读了以下内容:“它不要求缺少数组元素(即,从未设置的索引,已被删除或从未分配值)。”
battmanz

9

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

返回[0, 1, 2]。与Igor Shubin的出色答案非常相似,但欺骗性略低(一个字符更长)。

说明:

  • Array(3) // [undefined × 3]生成长度为n = 3的数组。不幸的是,这个数组对我们几乎没有用,所以我们必须…
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined]使数组可迭代。注意:null最常见的是apply的第一个arg,而0则更短。
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] 然后获取数组的键(之所以起作用,是因为Arrays是typeof数组是具有键索引的对象。
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] 并映射到键,将字符串转换为数字。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.