How to create an array containing 1...N

Asked 2023-09-20 20:53:54 View 775,288

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.

  • 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. - anyone
  • If anyone needs something more advanced, I created a node.js lib that does this for numbers, letters, negative/positive ranges, etc. github.com/jonschlinkert/fill-range. It's used in github.com/jonschlinkert/braces for brace expansion and github.com/jonschlinkert/micromatch for glob patterns - anyone
  • Another way of doing it can be like this : Array.from({length : 10}, (_, v) => v) - anyone
  • @SahilGupta Almost. If we want 1 to 10, we need to add 1, e.g. this: Array.from({length : 10}, (_, v) => v+1) - anyone
  • Instead of an array, define foo as object {} then add your own indexes with foo[i] = i; - anyone

Answers

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]

Answered   2023-09-20 20:53:54

  • 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 - anyone
  • Just change map(x => x++) to map(x => ++x) due to precedence increment happens after the value return :) - anyone
  • Er what!? Why map when you can simply slice? [...Array(N+1).keys()].slice(1) - anyone
  • Or don't use keys and only 1 map -> Array.from(Array(10)).map((e,i)=>i+1) - anyone
  • Or don't use keys and map and just pass a mapping function to from Array.from(Array(10), (e,i)=>i+1) - anyone

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.

Answered   2023-09-20 20:53:54

  • +1 for cleverness but please note this is orders of magnitude SLOWER than a primitive for loop: jsperf.com/array-magic-vs-for - anyone
  • 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. - anyone
  • 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; }) - anyone
  • @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) - anyone
  • IF this returns an array that starts at 1, it would actually answer the OP's question - anyone

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)

Answered   2023-09-20 20:53:54

  • Use k++ for arrays starting at 0 - anyone
  • If you want to increment, don't use k++, use ++k. - anyone
  • Beware Array.from is not supported in IE, unless you're poly-filling it. - anyone
  • To make the TS compiler happy consider replacing the unused param with lodash: Array.from({ length: 5 }, (_, k) => k + 1); - anyone
  • @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. - anyone

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/

Answered   2023-09-20 20:53:54

  • 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. - anyone
  • @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. - anyone
  • @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 ==> jsfiddle.net/ACMXp - anyone
  • 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;. - anyone
  • @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. - anyone

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




Answered   2023-09-20 20:53:54

  • 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.) - anyone
  • 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. - anyone
  • @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 stackoverflow.com/questions/36354325/… - anyone
  • This is wrong. All examples produce array of form [0,..,n-1] whereas question is for [1,...,n] - anyone
  • @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 - anyone

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

Answered   2023-09-20 20:53:54

  • +1 because it's a whole big O better than the nasty .join.splitversion - but I still think the humble loop is better. - anyone
  • const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()] - anyone
  • you don't need to add an arg to .fill() - anyone
  • 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? - anyone
  • For anyone else who is interested, the difference between Array(N) and Array(N).fill() is explained well here - anyone

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); // => []

Answered   2023-09-20 20:53:54

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

Answered   2023-09-20 20:53:54

  • 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. - anyone
  • 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. - anyone
  • Array.range(1, 5) would probably be more appropriate, but there is something kind of cool about writing [].range(1, 5). - anyone
  • "Rather make it a method of Array instead of Array.prototype" - What's the difference? You mean on a specific array only? - anyone
  • @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. - anyone

Performance

Today 2020.12.11 I performed 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 the fastest (except Firefox for big N - but it's fast there)
  • solution T is fastest on Firefox for big N
  • solutions M,P is 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 snippet only presents functions used in performance tests - it does not perform tests itself!

And here are example results for chrome

enter image description here

Answered   2023-09-20 20:53:54

  • That's a piece of work! Well done! - anyone
  • For those concerned with performance: the time it takes to create the array is only half of the story. You should also be concerned with the performance of using the array afterwards, which can be different depending on how the array is constructed, because engines have different internal representations for dense arrays and sparse arrays (aka arrays with "holes"), and a sparse array will retain the "sparse array" representation even if it becomes dense after construction. If in doubt, benchmark in a real use case. - anyone

the fastest way to fill an Array in v8 is:

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

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

Answered   2023-09-20 20:53:54

  • is there a way to do it without the extra variable _ - anyone
  • @bluejayke no :( - anyone
  • harsh, do you know what the source code of .map is? I'm not sure if its any faster than a for loop, but if not then theoretically we can just defineProperty and make a new one - anyone

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

Answered   2023-09-20 20:53:54

  • @JVG but not for the faster function? - anyone
  • Exactly right. It's this simple one liner everyone is looking for! - anyone
  • @supersan although its super slow :) - anyone
  • Modern javascript with the new fill method: Array(255).fill(0,0,255) - anyone
  • @cacoder how fast is it, how many arrays does it create and how many iterations? - anyone

Simply, this worked for me:

[...Array(5)].map(...)

Answered   2023-09-20 20:53:54

Using ES2015/ES6 spread operator

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

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

Answered   2023-09-20 20:53:54

  • i + 1 would make more sense than ++i. - anyone
  • Finally what I was looking for, I'd also specify that the 1, is the starting point tho - anyone

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]

Answered   2023-09-20 20:53:54

  • Also, why not new Array(10).join().split(',').map(function() {return ++arguments[1]});? - anyone
  • @Murplyx for some cases function with arguments inside will be not optimized by JS engine (true even for V8, see jsperf.com/arguments-vs-array-argument/2) - anyone
  • 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! - anyone

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.

Answered   2023-09-20 20:53:54

  • This comment gave me the idea to look up the range() function in RamdaJS, which happens to be the JS library I'm working with on my current project. Perfect. - anyone

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]

Answered   2023-09-20 20:53:54

  • It would be better to back up these claims with benchmarks. Try jsperf.com. - anyone
  • lol jsperf... pls Matt just beacuse you don't like my answer stop downvoting my others ... stackoverflow.com/a/18344296/2450730 ... use console.time() or how it's called ... NOT jsperf. - anyone
  • 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) - anyone
  • @cocco this is incorrect: var a=[],b=N;while(b--){a[b]=a+1}; - anyone
  • @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. ;-) - anyone

Solution for empty array and with just number in array

const arrayOne = new Array(10);
console.log(arrayOne);

const arrayTwo = [...Array(10).keys()];
console.log(arrayTwo);

var arrayThree = Array.from(Array(10).keys());
console.log(arrayThree);

const arrayStartWithOne = Array.from(Array(10).keys(), item => item + 1);
console.log(arrayStartWithOne)

Answered   2023-09-20 20:53:54

  • the question was about starting at 1, not 0 - anyone
  • @AndréKelling just updated the answer :-) - anyone

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);
// ➜ []

Answered   2023-09-20 20:53:54

the new way to filling Array is:

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

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

Answered   2023-09-20 20:53:54

  • This s a really good answer, although tecnically the question was from 1-N, not 0-(N-1) - anyone
  • Maybe we can use rest operator (...) like const [, ...array] = Array(5).keys(); - anyone

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)

Answered   2023-09-20 20:53:54

  • Since the array's values are actually filled using this solution, map and forEach will work. - anyone

Very simple and easy to generate exactly 1 - N

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

console.log('Result:', result);

Answered   2023-09-20 20:53:54

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

Answered   2023-09-20 20:53:54

  • Why down vote ? Long answer list hard to follow , so thought of summarizing . - anyone
  • isn't this 0-10? [...Array(10).keys()] - anyone
  • Webstorm suggests (new Array(10)).keys(), is it right? - anyone
  • (new Array(10)).keys() , returns ArrayIterator {} , not the array - anyone
  • This creates a global variable a. The loop should be for(var a=[];n--;a[n]=n+1) - anyone

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

Answered   2023-09-20 20:53:54

  • this is the hardest flex i've ever seen on stack overflow - anyone

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

Answered   2023-09-20 20:53:54

  • However, the Array(N) constructor creates an array with "holes", which may be less performant when it is actually used later. Engines use different internal representations for arrays depending on what's in them and whether they have "holes"; the internal representation can be downgraded if a hole is created, but is not upgraded when all holes are removed. In V8's terminology, this solution creates a HOLEY_SMI_ELEMENTS array, where a PACKED_SMI_ELEMENTS array would be preferable. v8.dev/blog/elements-kinds#the-elements-kind-lattice The V8 devs' advice is to use push instead. - anyone

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

Answered   2023-09-20 20:53:54

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)

Answered   2023-09-20 20:53:54

  • Similarly, you can also do the following in ES6: Array.from({length: N}, (v, k) => k). - anyone
  • 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. developer.mozilla.org/en/docs/Web/JavaScript/Reference/… - anyone
  • I'm weighing this vs the underscore range syntax, and range reads better. - anyone
  • 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 :) - anyone

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

Answered   2023-09-20 20:53:54

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

console.log(Array(...Array(9)).map((_, i) => i))

Answered   2023-09-20 20:53:54

  • Nice! Can also write this a bit more succinctly as [...Array(9)].map((_, i) => i) - anyone
for(var i,a=[i=0];i<10;a[i++]=i);

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

Answered   2023-09-20 20:53:54

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

Answered   2023-09-20 20:53:54