关于javascript:如何创建一个包含1 … N的数组

How to create an array containing 1…N

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

1
2
3
4
5
var foo = [];

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

对我而言,感觉应该有一种没有循环的方法。


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

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

使用扩展运算符的较短版本。

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


你可以这样做:

1
2
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)

result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

或随机值:

1
Array.apply(null, {length: N}).map(Function.call, Math.random)

result: [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()的工作原理,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
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 }),它将执行

1
2
3
4
5
6
7
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 is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.

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

兼容性

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


简单&amp; ES6简介:

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

因此:

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

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

1
2
3
4
5
const range = (N) => Array.from({length: N}, (v, k) => k+1) ;

console.log(
  range(5)
)


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

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

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

然后当你想要使用它时...(未优化,仅举例)

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

例如如果你不需要在数组中存储任何东西,你只需要一个可以迭代的正确长度的容器......这可能会更容易。

在这里看到它:http://jsfiddle.net/3kcvm/


在ES6中,您可以:

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

编辑:
自您更新问题后,将Array(45)更改为Array(N)

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


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

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

1
2
3
4
5
6
7
8
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方法,可以创建大小为N的临时数组来生成索引,然后创建一个可以分配给变量的新数组:

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

填充/地图

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

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

Array.from

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

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


使用非常流行的Underscore _.range方法

1
2
3
4
5
6
7
// _.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); // => []


1
2
3
4
5
6
7
function range(start, end) {
    var foo = [];
    for (var i = start; i <= end; i++) {
        foo.push(i);
    }
    return foo;
}

然后叫

1
var foo = range(1, 5);

在Javascript中没有内置的方法来执行此操作,但如果您需要多次执行此操作,则它是一个非常有效的实用程序函数。

编辑:在我看来,以下是一个更好的范围功能。也许只是因为我对LINQ有偏见,但我认为它在更多情况下更有用。你的旅费可能会改变。

1
2
3
4
5
6
7
8
9
10
11
12
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;
}


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

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

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


你可以用这个:

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

例如

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

将创建以下数组:

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


如果您碰巧在我的应用程序中使用d3.js,D3会提供一个辅助函数来为您执行此操作。

所以要从0到4获得一个数组,它就像:

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

并按照您的要求获取1到5之间的数组:

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

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


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

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

此外,尽管上面写的很短(而且很整洁),但我认为以下内容更快一些
(最大长度为:

127,Int8,

255,Uint8,

32,767,Int16,

65,535,Uint16,

2,147,483,647,Int32,

Uint32,4,294,967,295。

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

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

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

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

在完成此语句后,您可以在当前范围内简单地使用变量"arr";

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

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

因此,通过上述功能,上述超慢"简单单线程"变得超快,甚至更短:

1
range(1,14000);


ES6这样就可以了:

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

看看结果:

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


使用ES2015 / ES6扩展运算符

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

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


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

最短

1
var a=[],b=N;while(b--)a[b]=b+1;

排队

1
2
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开始

1
2
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]

想要一个功能?

1
2
3
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)

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

  • 如果你喜欢,不能没有

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

    要么

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


    填充Array的新方法是:

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

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


    如果您使用的是lodash,则可以使用_.range:

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

    Creates an array of numbers
    (positive and/or negative) progressing from start up to, but not
    including, end. A step of -1 is used if a negative start is specified
    without an end or step. If end is not specified, it's set to start
    with start then set to 0.

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    _.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);
    // ? []

    最终总结报告.. Drrruummm Rolll -

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

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

    但是,这个Code高尔夫球的无可争议的赢家(用最少的源代码来解决特定问题的比赛)是Niko Ruotsalainen。使用Array Constructor和ES6 spread运算符。 (大多数ES6语法都是有效的typeScript,但以下不是。所以在使用它时要明智)

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


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

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

    这个更短,可以用于其他序列,如生成偶数

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 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标准中的新Array方法和=>函数语法(在撰写本文时仅使用Firefox)。

    undefined填充孔:

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

    Array.from将"空洞"变为undefined,因此Array.map按预期工作:

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


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

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


    似乎目前在这个相当完整的答案列表中唯一的味道是一个以发电机为特色的;所以补救一下:

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

    因此可以使用:

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

    关于这一点的好处是你不必只是增加......为了从@ igor-shubin给出的答案中获取灵感,你可以很容易地创建一个random数组:

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

    而不是像冗长的在操作上昂贵的东西:

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

    你可以这样做:

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

    比字符串变体简单一点:

    1
    2
    3
    4
    5
    // 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((v, i) => i + 1) // [1, 2, 3, 4, 5, 6, 7]

    更新(1/4/2018):已更新以解决确切的OP问题。谢谢@lessless打电话给我!


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function sequence(max, step = 1) {
      return {
        [Symbol.iterator]: function* () {
          for (let i = 1; i <= max; i += step) yield i
        }
      }
    }

    console.log([...sequence(10)])


    只是另一个ES6版本。

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

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

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

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

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


    1
    Array(8).fill(0).map(Number.call, Number)

    窃取Igors Number.call技巧,但使用fill()稍微缩短。仅适用于ES6及以上版本。


    试试这个:

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

    如果您使用的是CoffeeScript,则可以通过执行以下操作来创建范围:

    1
    var foo = [1..5];

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


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

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

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


    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']然后获取数组的键(因为数组是数组的类型是具有键索引的对象)。
    • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]并映射键,将字符串转换为数字。

    您可以使用函数生成器或函数*表达式。
    这是[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function]并且函数生成器的引用链接到[https://developer.mozilla.org/en-美国/文档/网络/的JavaScript /参考/语句/函数。

    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]


    使用ES6

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


    你可以使用Es6中的数组填充和映射;就像有些人在答案中建议的那样。以下是几个例子:

    1
    2
    3
    4
    5
    6
    7
    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]

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


    即兴创作以上内容:

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

    一个人可以得到以下选择:

    1)Array.init到值v

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

    2)获得反转范围:

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


    我一直在寻找功能性解决方案,最后我得到了:

    1
    2
    3
    4
    5
    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(',')将稀疏数组转换为连续数组。


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

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

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

    并具有递归功能:

    1
    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

    编辑:另外两个解决方案

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

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


    我找到了这个老线程,因为我自己也在想这个问题,但我猜这里没有一个答案比原来的例子更容易,因为科科多科评论说,哈哈!

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

    1
    2
    3
    var foo = [];
    while (foo.length < N)
        foo.push( foo.length + 1 );

    输出比常规for循环至少稍快一点,并且希望不会出错(尽管计算方面可能更昂贵)。

    甚至可以这样做:

    1
    2
    3
    var foo= [];
    while (foo.length < N)
        foo.push( foo.length%4 + 1 );

    按顺序多次填充数组1-4。或者使用此方法用单个项填充数组,但我想在这种情况下,使用Array(N).fill(x)可能会更快。


    尝试将一个迭代器添加到Number的原型中。

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

    现在这些数字是可迭代的,只需将数字传递给Array.from即可

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

    或其他任何需要迭代的东西,比如循环。

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

    这有点令人费解,但也很酷。


    让我们分享我的:p

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

    ES5版本,效率低下,但也许是最短的一个表达式,而不是某个变量用例如填充的语句。一个for循环:

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


    所有这些都太复杂了。做就是了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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的范围

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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 ]

    只是为了好玩,我想建立伊恩亨利的答案。

    当然var array = new Array(N);将为您提供一个大小N的数组,但键和值将是相同的....然后将数组缩短为M,使用array.length = M ....但对于某些添加功能尝试:

    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
    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 1
        if (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 end
        for (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 is item: 1 of 12
    -7.5 is item: 2 of 12
    -16 is item: 3 of 12
    -24.5 is item: 4 of 12
    -33 is item: 5 of 12
    -41.5 is item: 6 of 12
    -50 is item: 7 of 12
    -58.5 is item: 8 of 12
    -67 is item: 9 of 12
    -75.5 is item: 10 of 12
    -84 is item: 11 of 12
    -92.5 is item: 12 of 12

    jsFiddle例子

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

    该函数创建一个数组,其中填充的值从start开始,以end结尾,增量为increment,其中

    1
    range(start, end, increment);

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


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

    1
    2
    3
    4
    5
    function range(n) {
        let a = Array(n);
        for (let i = 0; i < n; a[i++] = i);
        return a;
    }

    我可以生成的代码最少:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 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 array
    console.log([...zeroToN(10-1)])

    // but let's define a helper iterator function
    function 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));


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

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

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


    console.log(range(5));


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

    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
    // 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;
    // tests
    t0 = 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.");

    最快的是Array(n).fill(0).map(Number.call,Number),2nd是[... Array(n).keys()]

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


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

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

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

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

    显然我们需要一个功能JS的Array.unfold()工具。这是我们可以简单地实现自己的东西;

    1
    2
    3
    4
    5
    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。
    • s是用于通过f计算索引0的舒适座位的种子值。

    因此,如果我们打算创建一个充满1,4,9,16,25 ... n ^ 2等系列的数组,我们可以简单地做。

    1
    2
    3
    4
    5
    6
    7
    8
    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);


    功能小,它允许使用像
    [1,2]。范围(3,4) - > [1,2,3,4]它也适用于负参数。请享用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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);
    };

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


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

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


    Array.prototype.fill()

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

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


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

    1
    2
    3
    4
    5
    6
    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;
    })

    对我来说这是更有用的实用程序:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
     * 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;
    };

    Azle有一个名为create_array的实用程序函数,它为您提供了许多选项:

    创建一个从0到5的数组:

    1
    az.create_array(0, 5)

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

    创建一个从1到5的数组:

    1
    az.create_array(1, 5)

    [1,2,3,4,5]

    创建一个包含5个数组的数组:

    1
    az.create_array(1, 5, ['apples','carrots','oranges'])

    [
    ["苹果","胡萝卜","橙子"],
    ["苹果","胡萝卜","橙子"],
    ["苹果","胡萝卜","橙子"],
    ["苹果","胡萝卜","橙子"],
    ["苹果","胡萝卜","橘子"]
    ]

    创建一个包含5个对象的数组:

    1
    az.create_array(1, 5, {"color" :"orangered"})

    [{color:"orangered"},
    {color:"orangered"},
    {color:"orangered"},
    {color:"orangered"},
    {color:"orangered"}]

    创建一个包含6个随机数的数组:

    1
    az.create_array(0,5,'random') // default draws from 10

    [9,5,4,6,9,7]

    创建一个由1000个随机数组成的数组:

    1
    az.create_array(0,5,'random', 1000)

    [180,372,678,142,314,438]

    这是FIDDLE