How to create an array containing 1…N

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.

Answers:

Answer

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/

Answer

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

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.

Answer

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)

Answer

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




Answer

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

Answer

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

the fastest way to fill an Array in v8 is:

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

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

Answer

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

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

ES6 this will do the trick:

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

check out the result:

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

Answer

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.

Answer

Using ES2015/ES6 spread operator

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

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

Answer

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

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

the new way to filling Array is:

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

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

Answer

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

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

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

Answer

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

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

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

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

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

Answer

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

Answer

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

Answer
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.

Answer

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

Answer

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!

Answer

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.

Answer

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.
Answer

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

Using ES6

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

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.