1465

I'm looking for any alternatives to the below for creating a JavaScript array containing 1 through to N where N is only known at runtime.

var foo = [];

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

To me it feels like there should be a way of doing this without the loop.

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
Godders
  • 15,126
  • 4
  • 17
  • 18
  • 285
    After reading this entire page, I have come to the conclusion that your own simple for-loop is the simplest, most readable, and least error-prone. – Kokodoko May 08 '14 at 16:09
  • If anyone needs something more advanced, I created a node.js lib that does this for numbers, letters, negative/positive ranges, etc. https://github.com/jonschlinkert/fill-range. It's used in https://github.com/jonschlinkert/braces for brace expansion and https://github.com/jonschlinkert/micromatch for glob patterns – jonschlinkert Jun 09 '15 at 05:21
  • Another way of doing it can be like this : Array.from({length : 10}, (_, v) => v) – Sahil Gupta Aug 25 '19 at 00:15
  • @SahilGupta Almost. If we want 1 to 10, we need to add 1, e.g. this: Array.from({length : 10}, (_, v) => v+1) – Eureka Oct 13 '19 at 21:54
  • Instead of an array, define foo as object {} then add your own indexes with foo[i] = i; – SPlatten Feb 27 '20 at 13:42
  • @SPlatten why?? – bluejayke Apr 07 '20 at 11:31
  • @bluejayke, you don't need to push into the array you can just use i and test typeof foo[i] == "number" – SPlatten Apr 07 '20 at 17:05
  • Some of us are referring to use from which is not good at the performance: take a look here https://stackoverflow.com/a/61997323/13531204 – Soham May 25 '20 at 07:03

70 Answers70

2082

In ES6 using Array from() and keys() methods.

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

Shorter version using spread operator.

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

Start from 1 by passing map function to Array from(), with an object with a length property:

Array.from({length: 10}, (_, i) => i + 1)
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
meager
  • 209,754
  • 38
  • 307
  • 315
Niko Ruotsalainen
  • 30,972
  • 4
  • 20
  • 27
  • 89
    Just a note, this will always start at 0. Will need to chain a `map` to the array to adjust the values (`[...Array(10).keys()].map(x => x++);`) to start at 1 – Sterling Archer Dec 29 '15 at 21:42
  • 44
    Just change `map(x => x++)` to `map(x => ++x)` due to precedence increment happens after the value return :) – Brock Feb 12 '16 at 09:39
  • 128
    Er what!? Why `map` when you can simply `slice`? `[...Array(N+1).keys()].slice(1)` – Robin Apr 24 '16 at 19:51
  • 23
    Or don't use `keys` and only 1 map -> `Array.from(Array(10)).map((e,i)=>i+1)` – yonatanmn Jun 29 '16 at 14:03
  • 78
    Or don't use keys and map and just pass a mapping function to `from` `Array.from(Array(10), (e,i)=>i+1)` – Fabio Antunes Feb 21 '17 at 13:10
  • @Nate 's answer ```Array(N).fill().map((e,i)=>i+1)```` is better because you still need to call map on this if you want to start from 1 instead of 0 – dirkdig May 13 '17 at 18:16
  • yah you don't need keys here ! – dirkdig May 13 '17 at 18:21
  • 2
    [...Array(10).keys()] is the shortest and best answer in my opinion. If I wanted performance id go with a for loop. Otherwise id just need a way to remember an easy way of generating a list of numbers – Danilo Souza Morães Dec 05 '18 at 03:02
  • [...Array(11).keys()].splice(1) to create an array of numbers from 1 to 10 (vs 0 to 9, as [...Array(10).keys()] does), to fulfill the original question. Of course, replace 11 with N + 1. – Marc Apr 10 '20 at 20:02
856

You can do so:

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

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

or with random values:

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]

Explanation

First, note that Number.call(undefined, N) is equivalent to Number(N), which just returns N. We'll use that fact later.

Array.apply(null, [undefined, undefined, undefined]) is equivalent to Array(undefined, undefined, undefined), which produces a three-element array and assigns undefined to each element.

How can you generalize that to N elements? Consider how Array() works, which goes something like this:

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

Since ECMAScript 5, Function.prototype.apply(thisArg, argsArray) also accepts a duck-typed array-like object as its second parameter. If we invoke Array.apply(null, { length: N }), then it will execute

function Array() {
    var a = [];
    for (var i = 0; i < /* arguments.length = */ N; i++) {
        a.push(/* arguments[i] = */ undefined);
    }
    return a;
}

Now we have an N-element array, with each element set to undefined. When we call .map(callback, thisArg) on it, each element will be set to the result of callback.call(thisArg, element, index, array). Therefore, [undefined, undefined, …, undefined].map(Number.call, Number) would map each element to (Number.call).call(Number, undefined, index, array), which is the same as Number.call(undefined, index, array), which, as we observed earlier, evaluates to index. That completes the array whose elements are the same as their index.

Why go through the trouble of Array.apply(null, {length: N}) instead of just Array(N)? After all, both expressions would result an an N-element array of undefined elements. The difference is that in the former expression, each element is explicitly set to undefined, whereas in the latter, each element was never set. According to the documentation of .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.

Therefore, Array(N) is insufficient; Array(N).map(Number.call, Number) would result in an uninitialized array of length N.

Compatibility

Since this technique relies on behaviour of Function.prototype.apply() specified in ECMAScript 5, it will not work in pre-ECMAScript 5 browsers such as Chrome 14 and Internet Explorer 9.

200_success
  • 6,669
  • 1
  • 36
  • 68
Igor Shubin
  • 10,255
  • 3
  • 23
  • 33
  • 64
    +1 for cleverness but please note this is orders of magnitude SLOWER than a primitive for loop: http://jsperf.com/array-magic-vs-for – warpech Jan 24 '14 at 13:59
  • 8
    Very clever -- probably too so. Exploiting the fact that `Function.prototype.call`'s first param is the `this` object to map directly over `Array.prototype.map`'s iterator parameter has a certain brilliance to it. – Noah Freitas Aug 17 '14 at 22:46
  • 15
    This is really, really clever (borders on abusing JS). The really important insight here is the idiosyncrasy of `map` on unassigned values, in my opinion. Another version (and possibly slightly clearer, albeit longer) is: `Array.apply(null, { length: N }).map(function(element, index) { return index; })` – Ben Reich Oct 22 '14 at 14:23
  • 7
    @BenReich Even better (in terms of JS abuse levels): `Array.apply(null, new Array(N)).map(function(_,i) { return i; })` or, in case of es6 and arrow functions, even shorter: `Array.apply(null, new Array(N)).map((_,i) => i)` – oddy Nov 25 '14 at 00:07
  • If anyone else didn't immediately understand why you need to pass in `Number` as the 2nd arg to `map`, I wrote a bit about it here: https://gist.github.com/cowboy/4477847#gistcomment-1710084 – jackocnr Feb 28 '16 at 20:42
  • Wow thank you, also in that thread *{length: N} also seems to fail in PhantomJS, whereas Array(N) doesn't* which was exactly my problem. So I replaced it with `new Array(N).join().split(',').map(Number.call, Number);` – Francisco Presencia Apr 21 '16 at 03:24
  • A better, less tricky, more clear solution would be `Array(n).fill().map(Number.call, Number)`. Still, clever solution! – Jason Sep 30 '16 at 18:13
  • But fill() isn't supported in IE. See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/fill – Igor Shubin Oct 19 '16 at 12:29
  • 2
    IF this returns an array that starts at 1, it would actually answer the OP's question – Sarsaparilla May 17 '17 at 03:59
  • This is not the solution for OP's question! – Andre Figueiredo Jun 29 '17 at 20:01
  • 2
    it should be `Array.apply(null, {length: N + 1}).map(Number.call, Number).slice(1)` – Andre Figueiredo Jun 29 '17 at 20:09
  • Eh, `map` only defines one single argument, not two. What am I missing? The irony is that you have linked to the MDN article on `map` but it only specifies one argument for the function. – amn Mar 15 '20 at 14:27
  • I like this bc it works with typescript constraints in Angular 8. For Angular 9, other better options exist. – John Vandivier Apr 14 '20 at 22:57
583

Multiple ways using ES6

Using spread operator (...) and keys method

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

Fill/Map

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

Array.from

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

Array.from and { length: N } hack

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

Note about generalised form

All the forms above can produce arrays initialised to pretty much any desired values by changing i+1 to expression required (e.g. i*2, -i, 1+i*2, i%2 and etc). If expression can be expressed by some function f then the first form becomes simply

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

Examples:

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

Since the array is initialized with undefined on each position, the value of v will be undefined

Example showcasing all the forms

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)

More generic example with custom initialiser function f i.e.

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

or even simpler

[ ...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)
husayt
  • 12,616
  • 7
  • 45
  • 75
Abdennour TOUMI
  • 64,884
  • 28
  • 201
  • 207
  • 6
    Use k++ for arrays starting at 0 – Borgboy Mar 15 '17 at 01:55
  • 3
    If you want to increment, don't use `k++`, use `++k`. – Alex Feb 13 '18 at 18:42
  • 4
    Beware Array.from is not supported in IE, unless you're poly-filling it. – Lauren May 04 '18 at 21:30
  • As far as I'm aware this is the fastest + smallest way to do it. It only iterates over N once. Most other one-liners iterate over N at least twice. – willurd Jun 25 '18 at 21:39
  • 3
    To make the TS compiler happy consider replacing the unused param with lodash: Array.from({ length: 5 }, (_, k) => k + 1); – Journeycorner Jan 29 '19 at 12:22
  • @willurd how so? `[ ...Array(N).keys() ].map(f)` iterates at least twice, once for `...Array(N)`, another time for the `.keys()` part, and a third time for `.map` – bluejayke Jun 15 '20 at 02:33
  • 1
    @bluejayke I believe this answer has been edited since I commented, but I was talking specifically about `Array.from({length: 5}, (v, k) => k+1);`, which does indeed only iterate once. – willurd Jun 16 '20 at 03:57
  • 1
    @willurd ah yes, this is true, I like that solution, although even more efficient (without the extra var) would be `Array.from({length:10}, Number.call, i => i + 1)` – bluejayke Jun 16 '20 at 04:40
480

If I get what you are after, you want an array of numbers 1..n that you can later loop through.

If this is all you need, can you do this instead?

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

then when you want to use it... (un-optimized, just for example)

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

e.g. if you don't need to store anything in the array, you just need a container of the right length that you can iterate over... this might be easier.

See it in action here: http://jsfiddle.net/3kcvm/

meager
  • 209,754
  • 38
  • 307
  • 315
scunliffe
  • 57,883
  • 24
  • 118
  • 156
  • 5
    impressed you managed to phrase my question better than I could, you are indeed correct as on reflection all I need is an array of numbers that I can later loop through :) Thanks for your answer. – Godders Sep 19 '10 at 18:08
  • 175
    @Godders: If this is what you're looking for, why do you need an array? A simple `var n = 45;` and then looping from `1..n` would do. – casablanca Sep 19 '10 at 18:33
  • 2
    @casablanca: of course you are correct, can't believe i couldn't spot the simple answer before posting the question. Oh well, got there in the end. Thanks! – Godders Sep 19 '10 at 19:03
  • 4
    @Godders - To note, if you want to decrease the size of the array after it is created to length M, simply use `foo.length = M` --- The cut off info is lost. See it in action ==> http://jsfiddle.net/ACMXp/ – Peter Ajtai Sep 20 '10 at 02:11
  • 2
    Note since the indices don't exist with new Array(number), .forEach() won't work. The other answer may be preferable in that case. – mikemaccana Jun 19 '13 at 12:09
  • 31
    I really dont get why this answer even have upvotes... especially when the OP himself agrees it doesn't make any sense in a few comments above since he could just have done `var n = 45;`. – plalx Nov 04 '13 at 14:39
  • 93
    @scunliffe: Please note, that `new Array(45);` does not "create a 45 element array" (in same meaning as `[undefined,undefined,..undefined]` does). It rather "creates empty array with length = 45" (`[undefined x 45]`), same as `var foo = []; foo.length=45;`. That's why `forEach`, and `map` will not apply in this case. – tomalec Jan 24 '14 at 14:00
  • 1
    There are a lot of good answers here BUT THIS IS NOT ONE OF THEM. Search for a solution that uses Array.apply. – Corey Alix Nov 11 '15 at 16:37
  • 1
    @Corey - this met the needs of the OP when asked 5 years ago ;-) More importantly as pointed out in the other `Array.apply()` answer comments there is a serious performance issue compared to a basic for loop: http://jsperf.com/array-magic-vs-for – scunliffe Nov 11 '15 at 22:40
  • 2
    This "answer" is non-sense; foo={length:45} does the same thing. See "My 10000" at http://jsperf.com/array-magic-vs-for/11 for one 7x faster. – Corey Alix Nov 12 '15 at 14:59
  • If it meets the needs of the OP but does not answer the question, the question should be changed. We come here because of search for this question and get a different answer.. @scunliffe – vinnief Feb 21 '19 at 10:04
  • 1
    @casablanca Well, I need a set of numbers from 0 to n. Then I'll go around the array and splice a few of the numbers out of it. At some point I will be working with an array like [0, 1, 5, 6, 7, 13, 46, ...]. So this is a perfectly valid question. – Bitterblue Mar 27 '19 at 17:09
  • That was not the question. The OP wanted to fill the array with sequential values in one-liner – Dalibor Mar 30 '19 at 08:25
  • This is now can be considered a really incorrect answer - dear author would you mind updating it? – Peter Aron Zentai Jul 14 '20 at 11:06
370

Arrays innately manage their lengths. As they are traversed, their indexes can be held in memory and referenced at that point. If a random index needs to be known, the indexOf method can be used.


This said, for your needs you may just want to declare an array of a certain size:

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

Making use of the spread operator (...) and keys method, enables you to create a temporary array of size N to produce the indexes, and then a new array that can be assigned to your variable:

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

Fill/Map

You can first create the size of the array you need, fill it with undefined and then create a new array using map, which sets each element to the index.

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

Array.from

This should be initializing to length of size N and populating the array in one pass.

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



In lieu of the comments and confusion, if you really wanted to capture the values from 1..N in the above examples, there are a couple options:

  1. if the index is available, you can simply increment it by one (e.g., ++i).
  2. in cases where index is not used -- and possibly a more efficient way -- is to create your array but make N represent N+1, then shift off the front.

    So if you desire 100 numbers:

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




vol7ron
  • 35,981
  • 19
  • 104
  • 164
  • I believe this is useful when the array of numbers is being used for data that cannot be processed at the receiving end. (Like an HTML template that is just replacing values.) – Neil Monroe Aug 22 '12 at 15:01
  • Why someone would do this is to have an array of numbers to populate a dropdown list, giving the user a choice from 1 to 10. A small array by hand [1,2,3...10] make sense, but what if it's from 1 to 50? What if the end number changes? – CigarDoug Oct 23 '18 at 20:33
  • @CigarDoug I don’t doubt there is a usecase, but my guess it is small. Why would an array of numbers be needed, usually when iterating over an array an index would be used as part of the loop construct — either as an argument to the looping body function, or a counter variable — so holding the array of numbers seems trivial to just creating an array of specified width, or just a variable that holds the upper bound of the array. I can think of a few use cases, but none of those had been expressed by the OP – vol7ron Oct 23 '18 at 21:19
  • 5
    Like I said, I need to populate a dropdown with the numbers 1 through 10. That's all. There IS a usecase, MY usecase. That's how I found this page. So just building an array by hand was less complicated than anything I saw here. So my requirements aren't the requirements of the OP. But I have my answer. – CigarDoug Oct 24 '18 at 11:24
  • I’m not sure I fully understand your predicament, but IMHO that would be a poor usecase, leading to slow and confusing code. I’d say the OP shows a better way of doing that than using a loop, which is what I’d recommend for that case. The reasons for pre-populating a serial array are very limited and not worth expressing here as it’d be a minute probability that SO users would require it and those that would are so skilled they wouldn’t need to ask or research the question. – vol7ron Oct 24 '18 at 12:18
  • 1
    @vol7ron There is a usecase, I also have one. In angular, in paging, I want to show the pages in the footer that are clickable. So I loop the elements in a view with *ngFor="let p of pagesCounter". You have a better solution for that? BTW, check out https://stackoverflow.com/questions/36354325/angular-2-ngfor-using-numbers-instead-collections – Dalibor Mar 30 '19 at 08:47
  • @Dalibor I’d need to review Angular as I’ve mostly given up 2-way binding for React. Usually, for paging interfaces what’s mostly required is the length and some logic to determine and show numbers on each side of a cursor. I’d imagine you have several options in your case – vol7ron Mar 30 '19 at 16:43
  • I've posted the link. Those options you mention are discussed there – Dalibor Apr 01 '19 at 10:57
  • 1
    This is wrong. All examples produce array of form `[0,..,n-1]` whereas question is for `[1,...,n]` – husayt Feb 27 '20 at 13:18
  • @husayt yes, you’re right; however, that’s the point of the answer (as with the selected answer) to store the number from 0..N and display from 1..N+1, by adding 1 in the presentation – vol7ron Feb 27 '20 at 13:45
  • @husayt I’ll add that my original answer also expressed uncertainty and gave context to the 0..N suggestions. The most recent edit removed: `I know your question is asking to populate an array numerically, but I’m uncertain why you’d want to do this` which was followed by the bit stating that Arrays manage their lengths innately – vol7ron Feb 27 '20 at 13:53
  • @vol7ron your answer is useful, but still the title of the question is for `1..N` and that makes a subtle difference. Answer chosen is not the best answer. I guess question been edited over time and that is where the differences come from – husayt Feb 29 '20 at 12:16
  • @husayt let me try another way. This is an [XY Problem](https://en.m.wikipedia.org/wiki/XY_problem). It doesn’t matter that they asked about Y, because the real problem is X. In this case, X can be solved by using the Array’s index and Array methods to retrieve the index, or by incrementing the value in the presentation layer. If every number is off by 1, 5, or log baseN; make those changes when they’re used. The only reason to do it up front is for optimization, which unless this is used repeated for math (unlikely), optimization is costly and unnecessary. – vol7ron Feb 29 '20 at 14:33
198

In ES6 you can do:

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

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

Edit: Changed Array(45) to Array(N) since you've updated the question.

console.log(
  Array(45).fill(0).map((e,i)=>i+1)
);
mplungjan
  • 134,906
  • 25
  • 152
  • 209
Nate
  • 5,716
  • 3
  • 21
  • 29
  • 3
    +1 because it's a whole **big _O_** better than the nasty `.join.split`version - but I still think the humble loop is better. – Robin Apr 24 '16 at 19:33
  • I agree @Robin - Algorithmic complexity aside, the humble loop is always more readable. However, with the advent of lambdas in Java, I think `map` will soon become a standard for things like this. – Nate Apr 24 '16 at 19:37
  • yes `map` certainly seems very popular among these answers, but some of the ugliness required to first get a non-`undefined` filled array makes it less than ideal [IMHO], so I tried the mysterious voodoo of the generator (thoughts?)... – Robin Apr 24 '16 at 21:26
  • 4
    ```const gen = N => [...(function*(){let i=0;while(i – Robin Apr 24 '16 at 21:26
  • http://caniuse.com/#feat=arrow-functions - Note the browser support. Maybe you have to edit this array funtion into a normal anonymous function – CodeBrauer Jun 30 '16 at 09:44
  • @CodeBrauer note that I clearly stated it's ES6. I wouldn't have contributed another solution if it were the same as the others. – Nate Jun 30 '16 at 09:56
  • you don't need to add an arg to `.fill()` – Jason Sep 30 '16 at 18:19
  • @Jason I feel like at the time I did this the transpiler I was using generated an error with no arguments for `.fill()` but I could be wrong. I've updated accordingly however. – Nate Sep 30 '16 at 20:20
  • 8
    I don't understand why `.fill()` is necessary. I see that it is when I test on node's repl, but since `Array(1)[0] === undefined`, what difference does the call to fill() in `Array(1).fill(undefined)` make? – Dominic Oct 14 '16 at 09:45
  • 11
    For anyone else who is interested, the difference between Array(N) and Array(N).fill() is explained well [here](http://stackoverflow.com/questions/35013777/difference-between-arrayn-and-arrayn-fill) – Dominic Oct 17 '16 at 08:59
  • 1
    Array fill & map in one loop `Array.from(Array(45), (_, i) => i + 1))` – A1rPun May 29 '19 at 14:07
118

Use the very popular Underscore _.range method

// _.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); // => []
Evan
  • 7,132
  • 4
  • 28
  • 30
72
function range(start, end) {
    var foo = [];
    for (var i = start; i <= end; i++) {
        foo.push(i);
    }
    return foo;
}

Then called by

var foo = range(1, 5);

There is no built-in way to do this in Javascript, but it's a perfectly valid utility function to create if you need to do it more than once.

Edit: In my opinion, the following is a better range function. Maybe just because I'm biased by LINQ, but I think it's more useful in more cases. Your mileage may vary.

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;
}
Ian Henry
  • 21,297
  • 4
  • 47
  • 60
  • 2
    I like this. If you wanted to go the extra mile with it, you could declare it as Array.prototype.range = function(start, end) { ... };. Then, you can call range(x, y) on any Array object. – Zach Rattner Sep 19 '10 at 17:44
  • 9
    Rather make it a method of `Array` instead of `Array.prototype` as there is no reason (it might even be considered rather dumb) to have this method on every array. – adamse Sep 19 '10 at 17:47
  • 9
    `Array.range(1, 5)` would probably be more appropriate, but there is something kind of cool about writing `[].range(1, 5)`. – MooGoo Sep 19 '10 at 17:54
  • "Rather make it a method of Array instead of Array.prototype" - What's the difference? You mean on a specific array only? – pilau Apr 11 '13 at 13:32
  • 3
    @pilau Just as adamse says, it looks weird. If it's on the prototype, you can say `foo = [1, 2, 3]; bar = foo.range(0, 10);`. But that's just...confusing. `bar = Array.range(0, 10)` is a lot more clear and explicit. The range has nothing to do with the instance, so there's no reason to make it an instance method. – Ian Henry Apr 11 '13 at 14:19
  • @IanHenry Ah-ha. Thanks, I get it now. I'm not a native English speaker, so sometimes I get lost out of context :) – pilau Apr 11 '13 at 14:23
  • Sometimes the simplest looking solution is also the best. It's readable, it's easy to debug. Unlike some of the examples above using .apply and .map. – Kokodoko May 08 '14 at 16:07
55

the fastest way to fill an Array in v8 is:

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

result will be: [0, 1, 2, 3, 4]

Moha the almighty camel
  • 3,876
  • 3
  • 25
  • 48
аlex dykyі
  • 4,154
  • 23
  • 36
52

This question has a lot of complicated answers, but a simple one-liner:

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

Also, although the above is short (and neat) to write, I think the following is a bit faster (for a max length of:

127, Int8,

255, Uint8,

32,767, Int16,

65,535, Uint16,

2,147,483,647, Int32,

4,294,967,295, Uint32.

(based on the max integer values), also here's more on Typed Arrays):

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

Although this solution is also not so ideal, because it creates two arrays, and uses the extra variable declaration "$" (not sure any way to get around that using this method). I think the following solution is the absolute fastest possible way to do this:

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

Anytime after this statement is made, you can simple use the variable "arr" in the current scope;

If you want to make a simple function out of it (with some basic verification):

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

so, with the above function, the above super-slow "simple one-liner" becomes the super-fast, even-shorter:

range(1,14000);
bluejayke
  • 2,773
  • 2
  • 20
  • 50
43

You can use this:

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

for example

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

will create following array:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Abdennour TOUMI
  • 64,884
  • 28
  • 201
  • 207
nktssh
  • 2,081
  • 16
  • 22
  • Also, why not `new Array(10).join().split(',').map(function() {return ++arguments[1]});`? –  Jan 03 '16 at 20:31
  • 1
    @Murplyx for some cases function with arguments inside will be not optimized by JS engine (true even for V8, see https://jsperf.com/arguments-vs-array-argument/2) – nktssh Jan 05 '16 at 21:25
  • 4
    This is an interesting solution but it's entirely impractical - having to parse the array **3 times** (once to `join`, once to `split`, and once for the thing you actually want to do) is just not nice - I know they seem to have fallen out of favor for some reason, but it would be far better to simply use a good old fashioned **loop**! – Robin Apr 24 '16 at 19:29
43

Using ES2015/ES6 spread operator

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

console.log([...Array(10)].map((_, i) => i + 1))
Vlad Bezden
  • 59,971
  • 18
  • 206
  • 157
41

If you happen to be using d3.js in your app as I am, D3 provides a helper function that does this for you.

So to get an array from 0 to 4, it's as easy as:

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

and to get an array from 1 to 5, as you were requesting:

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

Check out this tutorial for more info.

Tyler Rick
  • 8,396
  • 6
  • 52
  • 56
  • This comment gave me the idea to look up [the range() function](http://ramdajs.com/0.19.0/docs/#range) in RamdaJS, which happens to be the JS library I'm working with on my current project. Perfect. – morphatic Dec 24 '15 at 05:34
41

This is probably the fastest way to generate an array of numbers

Shortest

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

Inline

var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]

If you want to start from 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]

Want a 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]

WHY?

  1. while is the fastest loop

  2. Direct setting is faster than push

  3. [] is faster than new Array(10)

  4. it's short... look the first code. then look at all other functions in here.

If you like can't live without for

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

or

for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
Jeff Huijsmans
  • 1,263
  • 14
  • 30
cocco
  • 15,256
  • 6
  • 53
  • 73
  • 8
    It would be better to back up these claims with benchmarks. Try http://jsperf.com. – Matt Ball Aug 21 '13 at 13:58
  • 3
    lol jsperf... pls Matt just beacuse you don't like my answer stop downvoting my others ... http://stackoverflow.com/a/18344296/2450730 ... use console.time() or how it's called ... NOT jsperf. – cocco Aug 21 '13 at 14:00
  • 4
    FYI: As John Reisig first published a few years ago - on some platforms (meaning windows:P) time is being fed to the browser once every 16ms. Also there are other problems with measuring time of execution in multitasking environments. jsperf.com has implemented running the tests so that they are statistically correct. It's ok to run `console.time()` to get an intuition, but for a proof, you need jsperf.com AND it shows you cross-browser results from other people (different hardware etc) – naugtur Sep 14 '13 at 08:58
  • you can't test the while loop in jsperf ... as you always have to redefine the length.anyway the while-- loop is the fastest on every browser.for is is almost as fast then while but all the other new ways are very slow like forEach , filter map... it's always faster to write you own function with for or while. – cocco Sep 15 '13 at 10:49
  • it's also logically correct as you just pass only one variable (the length of the array).. and not 3 parameters... for give's you alot more control and yeah most modern browsers are pushing to get the for loop as fast a possible.. but i did this tests also many years ago... starting with a 200mhz pentium... :) – cocco Sep 15 '13 at 11:01
  • 3
    @cocco this is incorrect: `var a=[],b=N;while(b--){a[b]=a+1};` – vintagexav May 15 '15 at 23:28
  • sure, it's b+1, don't copy and past... understand what you do! – cocco May 16 '15 at 07:14
  • 1
    `var a=[],b=10;while(b--)a[b]=a+1;` -> `",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,11,11,,,,,,,,,,,,,,,,,,11,11,,,,,,,,,,`… Definitely wrong. – royhowie May 16 '15 at 07:55
  • +1 cool, someone actually read the function.... after almost one year!!!! yeah you both are right it's not "a+1" but "b+1". Anyway the others are working correctly! – cocco May 16 '15 at 08:00
  • btw test it yourself on some sites like jsperf... how fast the old while is! compare it with the other functions in here!! – cocco May 16 '15 at 08:02
  • 5
    @cocco— *while* isn't **always** faster than other loops. In some browsers, a decrementing while loop is much slower than a for loop, you can't make general statements about javascript performance like that because there are so many implementations with so many different optimisations. However, in general I like your approach. ;-) – RobG Aug 09 '15 at 23:57
  • 1
    Massive **+1** - someone else actually cares about precious time - I was beginning to think I was the only! I like the breakdown (points 1-4), even if (as @RobG mentions) they may not always be 100% accurate it does help people to see why your solution is good. – Robin Apr 24 '16 at 19:40
  • 1
    *"This is probably the fastest way"*... Nope. With all the spaces stripped out, the code actually takes **longer** to read and understand. – Dem Pilafian Jan 01 '19 at 23:57
  • `[] is faster than new Array(10)` Its faster if you just create it and don't need to use it. But as soon as you fill elements, it will grow and take more time to get to Array(10). – Yuriy Grinevich Mar 12 '19 at 15:45
  • Wow, saying `while` is the fastest loop is pure ignorance. JS is a constantly evolving high-level language. Even if you analyse and optimize the entire **bytecode**, you'll realize that performance can vary to the point of noise between implementations. I've often tried to use `while` thinking it's faster but I realize `for` is 10x more convenient for my purpose and the performance difference is almost immeasurable. Plus this answer is from 2013, latest version of JS engines are way more optimized now. – bryc Dec 27 '19 at 00:10
35

the new way to filling Array is:

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

result will be: [0, 1, 2, 3, 4]

аlex dykyі
  • 4,154
  • 23
  • 36
33

If you are using lodash, you can use _.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.

Examples:

_.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);
// ➜ []
k0pernikus
  • 41,137
  • 49
  • 170
  • 286
Hongbo Miao
  • 31,551
  • 46
  • 124
  • 206
31

with ES6 you can do:

// `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)
28

Final Summary report .. Drrruummm Rolll -

This is the shortest code to generate an Array of size N (here 10) without using ES6. Cocco's version above is close but not the shortest.

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

But the undisputed winner of this Code golf(competition to solve a particular problem in the fewest bytes of source code) is Niko Ruotsalainen . Using Array Constructor and ES6 spread operator . (Most of the ES6 syntax is valid typeScript, but following is not. So be judicious while using it)

[...Array(10).keys()]
Community
  • 1
  • 1
sapy
  • 6,665
  • 6
  • 40
  • 51
  • Why down vote ? Long answer list hard to follow , so thought of summarizing . – sapy Feb 28 '16 at 05:15
  • isn't this 0-10? [...Array(10).keys()] – Greg May 25 '16 at 18:19
  • Webstorm suggests (new Array(10)).keys(), is it right? – Guy Jul 15 '16 at 09:09
  • (new Array(10)).keys() , returns ArrayIterator {} , not the array – sapy Jul 15 '16 at 19:34
  • This creates a global variable `a`. The loop should be `for(var a=[];n--;a[n]=n+1)` – kube Aug 04 '16 at 17:09
  • you missed the `Code golf(competition to solve a particular problem in the fewest bytes of source code)` part in the answer :) – sapy Aug 04 '16 at 17:33
  • @kube - if you care about the global, you can shave *2* whole chars off your `for(var a=[]...` version: `(function(n,a){for(a=[];n--;a[n]=n+1);return a})(10)` – Robin Jul 30 '19 at 00:16
25

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

With Delta

For javascript

smallest and one-liner
[...Array(N)].map((v, i) => from + i * step);

Examples and other alternatives

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]
Range Function
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]
As Iterators
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 loop
for (i of new Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2
As Generators Only
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 loop
for (i of Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2

// Lazy loaded way
const number0toInf = Range(Infinity);
number0toInf.next().value;
//=> 0
number0toInf.next().value;
//=> 1
// ...

From-To with steps/delta

using iterators
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]
using Generators
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;
//=> 4
even4to10.next().value;
//=> 6
even4to10.next().value;
//=> 8
even4to10.next().value;
//=> 10
even4to10.next().value;
//=> undefined

For 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);
nkitku
  • 1,507
  • 15
  • 14
22

There is another way in ES6, using Array.from which takes 2 arguments, the first is an arrayLike (in this case an object with length property), and the second is a mapping function (in this case we map the item to its index)

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

this is shorter and can be used for other sequences like generating even numbers

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

Also this has better performance than most other ways because it only loops once through the array. Check the snippit for some comparisons

// 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")
gafi
  • 9,663
  • 2
  • 27
  • 28
  • Hey that's neat, I like it. However it doesn't return the results OP expects. To do that it would need to be written as `Array.from({length:N}, (v,i) => i+1)` – CervEd Oct 22 '16 at 11:17
  • These neato hacks are still [5-10x slower than a good old for loop](https://jsfiddle.net/ChefGabe/yLzpo2p5/). – Dan Dascalescu Sep 13 '18 at 23:22
22

Very simple and easy to generate exactly 1 - N

const [, ...result] = Array(11).keys();

console.log('Result:', result);
yivi
  • 23,845
  • 12
  • 64
  • 89
Diamond
  • 2,754
  • 1
  • 9
  • 31
21

Performance

Today 2020.12.11 I perform tests on MacOs HighSierra 10.13.6 on Chrome v87, Safari v13.1.2 and Firefox v83 for chosen solutions.

Results

For all browsers

  • solution O (based on while) is fastest (except Firefox for big N - but it's fast there)
  • solution T is fastest on Firefox for big N
  • solutions M,P are fast for small N
  • solution V (lodash) is fast for big N
  • solution W,X are slow for small N
  • solution F is slow

enter image description here

Details

I perform 2 tests cases:

  • for small N = 10 - you can run it HERE
  • for big N = 1000000 - you can run it HERE

Below snippet presents all tested solutions A B C D E F G H I J K L M N O P Q R S T U V W X

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 shippet only presents functions used in performance tests - it not perform tests itself!

And here are example results for chrome

enter image description here

yivi
  • 23,845
  • 12
  • 64
  • 89
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
18

Using new Array methods and => function syntax from ES6 standard (only Firefox at the time of writing).

By filling holes with undefined:

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

Array.from turns "holes" into undefined so Array.map works as expected:

Array.from(Array(5)).map((_, i) => i + 1)
szymzet
  • 575
  • 4
  • 11
  • 8
    Similarly, you can also do the following in ES6: `Array.from({length: N}, (v, k) => k)`. – XåpplI'-I0llwlg'I - Jun 08 '15 at 09:19
  • Xappli's approach is preferred: Array.from was created for almost this exact scenario, and it implies a mapping callback. It's an excellent solution to the general problem of wanting to use Array methods on something array-like, without resorting to verbose approaches like `Array.prototype.map.call`, e.g. for NodeLists returned from `document.querySelectorAll`. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from – Josh from Qaribou Oct 16 '15 at 02:50
  • I'm weighing this vs the underscore range syntax, and range reads better. – ooolala Nov 06 '15 at 05:13
  • Technically it's not `Array.from` which turns the sparse values into undefined. Rather `Array(5)` is called as an arguments object which in turn interprets the sparse values as undefined values :) – CervEd Oct 22 '16 at 11:21
18

In ES6:

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

or better yet (without the extra variable _ and without the extra slice call):

Array.from({length:1000}, Number.call, i => i + 1)

Or for slightly faster results, you can use Uint8Array, if your list is shorter than 256 results (or you can use the other Uint lists depending on how short the list is, like Uint16 for a max number of 65535, or Uint32 for a max of 4294967295 etc. Officially, these typed arrays were only added in ES6 though). For example:

Uint8Array.from({length:10}, Number.call, i => i + 1)

ES5:

Array.apply(0, {length: 1000}).map(function(){return arguments[1]+1});

Alternatively, in ES5, for the map function (like second parameter to the Array.from function in ES6 above), you can use Number.call

Array.apply(0,{length:1000}).map(Number.call,Number).slice(1)

Or, if you're against the .slice here also, you can do the ES5 equivalent of the above (from ES6), like:

Array.apply(0,{length:1000}).map(Number.call, Function("i","return i+1"))
bluejayke
  • 2,773
  • 2
  • 20
  • 50
15

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

console.log(Array(...Array(9)).map((_, i) => i))
аlex dykyі
  • 4,154
  • 23
  • 36
14
for(var i,a=[i=0];i<10;a[i++]=i);

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

SammieFox
  • 438
  • 1
  • 6
  • 4
12

It seems the only flavor not currently in this rather complete list of answers is one featuring a generator; so to remedy that:

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

which can be used thus:

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

The nice thing about this is you don't just have to increment... To take inspiration from the answer @igor-shubin gave, you could create an array of randoms very easily:

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

And rather than something lengthy operationally expensive like:

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

you could instead do:

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

Fast

This solution is probably fastest it is inspired by lodash _.range function (but my is simpler and faster)

let N=10, i=0, a=Array(N);

while(i<N) a[i++]=i;



console.log(a);

Performance advantages over current (2020.12.11) existing answers based on while/for

  • memory is allocated once at the beginning by a=Array(N)
  • increasing index i++ is used - which looks is about 30% faster than decreasing index i-- (probably because CPU cache memory faster in forward direction)

Speed tests with more than 20 other solutions was conducted in this answer

Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
11

You can use Array fill and map from Es6; just like some few people suggested in the answers they gave for this question. Below are some few examples:

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]

I prefer this because I find it straight forward and easier.

Oluwagbemi Kadri
  • 251
  • 4
  • 15
10
Array(8).fill(0).map(Number.call, Number)

Stealing Igors Number.call trick but using fill() to shorten slightly. Only works with ES6 and above.

AP.
  • 6,216
  • 2
  • 22
  • 31
Tom
  • 2,296
  • 3
  • 26
  • 35
10

Just another ES6 version.

By making use of Array.from second optional argument:

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

We can build the numbered array from the empty Array(10) positions:

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

var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);
zurfyx
  • 23,843
  • 15
  • 103
  • 130
9

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

Returns [0, 1, 2]. Very similar to Igor Shubin's excellent answer, but with slightly less trickery (and one character longer).

Explanation:

  • Array(3) // [undefined × 3] Generate an array of length n=3. Unfortunately this array is almost useless to us, so we have to…
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined] make the array iterable. Note: null's more common as apply's first arg but 0's shorter.
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] then get the keys of the array (works because Arrays are the typeof array is an object with indexes for keys.
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] and map over the keys, converting strings to numbers.
Community
  • 1
  • 1
mLuby
  • 653
  • 7
  • 15
9

Using ES6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);
Geoffrey Abdallah
  • 3,009
  • 12
  • 25
  • Thanks! This was the most elegant answer in my opinion! One could also use `Array.from(Array(n))` if the spread operator is not supported. – Amit Oct 08 '17 at 08:36
  • At first I didn't know why you had to use the spread operator, but then I read the following about [`map` on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Description): "It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value)." – battmanz Feb 09 '18 at 19:06
9

Iterable version using a generator function that doesn't modify 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)])
yckart
  • 28,174
  • 7
  • 112
  • 121
  • FWIW, you can use object function property shorthand to shorten this code somewhat: `{*[Symbol.iterator]() {... etc ...}}` See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#New_notations_in_ECMAScript_2015 – broofa Sep 28 '19 at 22:11
9
Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));

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

Tim
  • 821
  • 9
  • 13
9

I would do it this way using ...Array(N).keys()

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

console.log(foo)
Islam Elshobokshy
  • 8,788
  • 6
  • 20
  • 45
9

You can just do this:

var arr = Array.from(Array(10).keys())
arr.shift()
console.log(arr)
yivi
  • 23,845
  • 12
  • 64
  • 89
Belhadjer Samir
  • 1,019
  • 2
  • 11
8

A little bit simpler than the string variant:

// 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]

Update (1/4/2018): Updated to address the exact OP question. Thanks @lessless for calling this out!

Matt Lo
  • 4,543
  • 1
  • 17
  • 21
8

You can use a function generator or function* expression. Here's [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function] And a reference to the function generator link to [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]

Juan Gaitán
  • 583
  • 6
  • 14
7

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

dabeng
  • 762
  • 9
  • 7
  • 4
    Additional context may be helpful to preserve the long-term value of the answer. Please consider adding additional supplementary information to expand on the answer. – Matthew Morek Jun 16 '20 at 13:01
  • `(v, i) => i + 1` is a map (see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)), it takes current index and sets the value to be one more than the index - you get `[1, 2, 3, 4, 5]` if N = 5 — that's a very elegant solution – revelt Sep 29 '20 at 07:17
6

The following function returns an array populated with numbers:

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

Note that an array created with the array constructor consists of holes, so it cannot be traversed with array functions like map. Hence using the Array.apply function.

Ghasem Kiani
  • 109
  • 1
  • 3
  • If you want your array to start with the value of 1, all you got to do is `return index +1` – AllJs May 24 '21 at 07:35
6

I didn't see any solution based on recursive functions (and never wrote recursive functions myself) so here is my try.

Note that array.push(something) returns the new length of the array:

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

And with a recursive function:

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

EDIT : two other solutions

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

and

var a = []
var i=setInterval(function(){a.length===5?clearInterval(i):a.push(a.length+1)}) 
radsoc
  • 500
  • 5
  • 5
  • `Object.keys(new Int8Array(N))` is a clever hack, and faster than the `Array.apply()` and `Array.from()` solutions, but with ES2015, we have a faster and less weird-looking solution, `[...Array(11).keys()].slice(1)`. – Dan Dascalescu Sep 13 '18 at 23:31
5

I was looking for a functional solution and I ended up with:

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

console.log(numbers(1, 9));

Note: join().split(',') transforms the sparse array into a contiguous one.

Bruno Jouhier
  • 973
  • 8
  • 10
  • 2
    That's a seriously inefficient approach. It creates 3 arrays, a string, and calls a function `max - min` times. Consider: `for (var i=max-min+1, a=[]; i--;) a[i] = min+i;` which creates one array and does one loop and is less to write. ;-) – RobG Aug 09 '15 at 23:54
  • See http://stackoverflow.com/questions/12760643/how-to-convert-a-javascript-typed-array-into-a-javascript-array, Array.prototype.slice.call(new Float32Array (12)); – Corey Alix Nov 11 '15 at 16:18
  • I was building something similar and settled on `return Array((max+1)-min).fill().map((_,i) => i + min);`. It dodges the off-by-one issue and works for any number assuming max is bigger than min. – rtpHarry Mar 07 '21 at 01:51
  • (im not sure about efficiency, at the moment I'm just trying to write everything in functional form to get used it) – rtpHarry Mar 07 '21 at 01:52
5

Improvising on the above:

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

one can get the following options:

1) Array.init to value v

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

2) get a reversed range:

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

All of these are too complicated. Just do:

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 ]

Or to do a range from a to b

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 ]
jonschlinkert
  • 10,046
  • 3
  • 38
  • 50
3

Let's share mine :p

Math.pow(2, 10).toString(2).split('').slice(1).map((_,j) => ++j)
nfroidure
  • 1,375
  • 10
  • 18
3

The least codes I could produce:

for(foo=[x=100]; x; foo[x-1]=x--);
console.log(foo);
Coisox
  • 870
  • 1
  • 7
  • 19
3

Try this:

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

If you are using CoffeeScript, you can create a range by doing:

var foo = [1..5]; 

Otherwise, if you are using vanilla JavaScript, you'll have to use a loop if you want to initialize an array up to a variable length.

Gaʀʀʏ
  • 3,952
  • 2
  • 34
  • 56
Zach Rattner
  • 18,673
  • 9
  • 53
  • 79
  • 3
    This answer is unfortunately not valid anymore since the OP updated his question. – BalusC Sep 19 '10 at 17:46
  • If you can use coffeescript, you can specify a range to quickly create arrays with `n` elements. For example: `arr = [1..10]` will produce `arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]` – Rui Nunes Mar 30 '16 at 08:55
3

Try adding an iterator to Number's prototype.

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

Now that numbers are iterable, simply pass a number to Array.from

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

or anywhere else an iterable is required, like for...of loops.

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

It's somewhat convoluted, but also cool.

John Henry
  • 942
  • 1
  • 12
  • 19
  • I want to give credit to @Robin, who posted a similar answer a few months before me: http://stackoverflow.com/a/36828957/1290781 – John Henry Nov 15 '16 at 18:48
3

I found this old thread because I was wondering about the same myself, but I guess none of the answers here were easier than your original example as Kokodoko commented, haha!

I ended up using this method myself:

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

Which is at least slightly faster to type out than a regular for-loop, and hopefully not error-prone (though it might be more expensive computational-wise).

Can even do something like:

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

to fill the array with 1-4 multiple times in sequential order. Or use this method to fill the array with a single item, though I guess in that case it might be faster to just use Array(N).fill(x).

Sᴀᴍ Onᴇᴌᴀ
  • 7,491
  • 8
  • 27
  • 56
Mythril
  • 64
  • 2
3

ES6 solution using recursion. Different than all other solutions

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


console.log(range(5));
Sumer
  • 1,591
  • 15
  • 17
  • How fast is it though, how many iterations occur? More than N? – bluejayke Jun 26 '19 at 16:01
  • 1
    To elaborate on this great answer, both offset and step are supported: `Array.from({length: 5}, (v, k) => k* step + offset);` – pscl Nov 14 '19 at 22:40
3

Try this

const foo = numberOfItems=> [...Array(numberOfItems).keys()].map(i => i+1);
Praveen Ramanayake
  • 181
  • 1
  • 1
  • 12
3

Based on high voted answer and its high voted comment.

const range = (from, to) => [...Array(to + 1).keys()].slice(from);

// usage
let test = [];
test = range(5, 10);
console.log(test); // output: [ 5, 6, 7, 8, 9, 10 ]
Mehdi Dehghani
  • 8,186
  • 5
  • 49
  • 53
3

no for create array in ES6 solutions

js no for 100 array

1. padStart


// string arr
const 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 arr
const 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. Typed Arrays

Uint8Array

// number arr
const 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 arr
const 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"]
xgqfrms
  • 5,516
  • 1
  • 37
  • 42
3

Try this one

[...Array.from({length:30}).keys()]
аlex dykyі
  • 4,154
  • 23
  • 36
2

The question was for alternatives to this technique but I wanted to share the faster way of doing this. It's nearly identical to the code in the question but it allocates memory instead of using push:

function range(n) {
    let a = Array(n);
    for (let i = 0; i < n; a[i++] = i);
    return a;
}
Corey Alix
  • 2,349
  • 2
  • 21
  • 35
2

Just for fun, I wanted to build off of Ian Henry's answer.

Of course var array = new Array(N); will give you an array of size N, but the keys and values will be identical.... then to shorten the array to size M, use array.length = M.... but for some added functionality try:

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/>'); 
}​

Output of the above:

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 example

This function makes use of the automatically generated arguments array.

The function creates an array filled with values beginning at start and ending at end with increments of size increment, where

range(start, end, increment);

Each value has a default and the sign of the increment doesn't matter, since the direction of incrementation depends on the relative sizes of start and end.

Community
  • 1
  • 1
Peter Ajtai
  • 54,199
  • 12
  • 118
  • 138
2
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]
kenberkeley
  • 4,183
  • 25
  • 23
2

ES5 version, inefficient, but perhaps the shortest one that's an expression, not some statement where a variable is populated with eg. a for loop:

(Array(N)+'').split(',').map(function(d,i){return i})
Robert Monfera
  • 1,457
  • 1
  • 17
  • 12
2

// 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));
FredG
  • 393
  • 4
  • 6
2

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

webjay
  • 4,668
  • 8
  • 37
  • 53
1

For small ranges a slice is nice. N is only known at runtime, so:

[0, 1, 2, 3, 4, 5].slice(0, N+1)
Dan Dascalescu
  • 110,650
  • 40
  • 276
  • 363
dansalmo
  • 10,338
  • 5
  • 50
  • 49
1

Well, simple but important question. Functional JS definitely lacks a generic unfold method under the Array object since we may need to create an array of numeric items not only simple [1,2,3,...,111] but a series resulting from a function, may be like x => x*2 instead of x => x

Currently, to perform this job we have to rely on the Array.prototype.map() method. However in order to use Array.prototype.map() we need to know the size of the array in advance. Well still.. if we don't know the size, then we can utilize Array.prototype.reduce() but Array.prototype.reduce() is intended for reducing (folding) not unfolding right..?

So obviously we need an Array.unfold() tool in functional JS. This is something that we can simply implement ourselves just 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);
};

Arrays.unfold(p,f,t,v) takes 4 arguments.

  • p This is a function which defines where to stop. The p function takes 3 arguments like many array functors do. The value, the index and the currently resulting array. It shall return a Boolean value. When it returns a true the recursive iteration stops.
  • f This is a function to return the next items functional value.
  • t This is a function to return the next argument to feed to f in the next turn.
  • s Is the seed value that will be used to calculate the comfortable seat of index 0 by f.

So if we intend to create an array filled with a series like 1,4,9,16,25...n^2 we can simply do 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);
Redu
  • 19,106
  • 4
  • 44
  • 59
1

for me this is more useful utility:

/**
 * 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;
};
Fareed Alnamrouti
  • 26,439
  • 4
  • 77
  • 71
1

Here is the summary (run in console):

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

The fastest is Array(n).fill(0).map(Number.call, Number), 2nd is [...Array(n).keys()]

But '...rangeIter' way is quite handy (can be inlined), fast and more powerful

SalientBrain
  • 1,984
  • 13
  • 16
1

for start from 1:

[...Array(31).keys()].map(a=>a+1)
  • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – mufazmi May 21 '21 at 18:22
0

There is small function, it allow to use construction like [1, 2].range(3, 4) -> [1, 2, 3, 4] also it works with negative params. Enjoy.

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

to get array with n random numbers between min, max (not unique though)

function callItWhatYouWant(n, min, max) {
    return Array.apply(null, {length: n}).map(Function.call, function(){return Math.floor(Math.random()*(max-min+1)+min)})
}
Nour Wolf
  • 1,860
  • 23
  • 22
0

Array.prototype.fill()

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

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

bjhamltn
  • 370
  • 4
  • 6
0

As there are a lot of good answers this might be an option as well, you can also create a function with the below and it will work for any combination of numbers

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;
})
emcee22
  • 1,755
  • 4
  • 21
  • 31