237

Say I have the following checkbox:

<input type="checkbox" value="1-25" />

To get the two numbers that define the boundaries of range I'm looking for, I use the following jQuery:

var value = $(this).val();
var lowEnd = Number(value.split('-')[0]);
var highEnd = Number(value.split('-')[1]);

How do I then create an array that contains all integers between lowEnd and highEnd, including lowEnd and highEnd themselves? For this specific example, obviously, the resulting array would be:

[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]
40 Degree Day
  • 2,573
  • 4
  • 21
  • 15
  • Nothing of note. Creating the array is part of a larger issue I've been trying to work through, which I had been approaching from a completely different direction. I realized this might be a more effective approach, despite the fact arrays are one element of JS I've always had trouble fully grasping. Unfortunately, I couldn't find anything on Stack Overflow or elsewhere that specifically dealt with this question. – 40 Degree Day Nov 09 '11 at 18:08
  • The duplicated question is not the same. The duped Q is about simply creating a range, whereas this question requests to create a range between two pre-determined variables. Most of the answers in the other question do not solve this question as you can't use variables (such as `Array.from()`). – James Jul 04 '21 at 08:14

24 Answers24

245
var list = [];
for (var i = lowEnd; i <= highEnd; i++) {
    list.push(i);
}
Ben
  • 10,056
  • 5
  • 41
  • 42
  • 14
    And just for general information, in CoffeeScript it would look like "1..25" which actually transforms to something like this in JavaScript. So there is no easier way to do this. – FreeCandies Nov 09 '11 at 18:02
  • 9
    @FreeCandies - True, CoffeeScript has this convenience, but you'd still have to run it through the compiler - slow or inconvenient, and you'd remain clueless as to how to do it by hand. I sincerely hope we're not going to replace the 'just use jQuery' era with 'just use CoffeeScript' – meouw Nov 09 '11 at 20:23
  • 4
    Note, the correct coffeescript notation is [1..25] – Alain Jacomet Forte Aug 22 '13 at 16:51
167

ES6 :

Use Array.from (docs here):

console.log(
   Array.from({length:5},(v,k)=>k+1)
)
Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
  • 2
    ..then , ... : `(1)['..'](10).forEach(function(e){console.log(e)})` . . for example – Abdennour TOUMI Jan 31 '15 at 02:00
  • 2
    Oh my, lambda expressions in javascript! Thanks for the info. Note though, here they state why one should put the body into parantheses, too: https://www.vinta.com.br/blog/2015/javascript-lambda-and-arrow-functions/ Like `(v,k)=>(k+1)` – Markus-Hermann May 08 '20 at 08:56
  • 12
    How is this answer relevant when the question is how to get the range between two numbers? – Operator Jan 13 '21 at 07:23
  • Wiith this you can create the range: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#sequence_generator_range – maidi Feb 16 '21 at 22:03
  • 2
    Creating a sequence between two numbers with `Array.from` is described here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#sequence_generator_range – maidi Feb 16 '21 at 22:09
  • Would like to add something to it. To have it in a range `Array.from({length:end+1-start}, (v,k) => start+k)` So, for example, if start is 10 and end is 18, it will generate all the numbers between 10, 18 a.k.a it will include both the start and end number in the array. – Koushik Das Apr 27 '21 at 08:06
135

In JavaScript ES6:

function range(start, end) {
  return Array(end - start + 1).fill().map((_, idx) => start + idx)
}
var result = range(9, 18); // [9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
console.log(result);

For completeness, here it is with an optional step parameter.

function range(start, end, step = 1) {
  const len = Math.floor((end - start) / step) + 1
  return Array(len).fill().map((_, idx) => start + (idx * step))
}
var result = range(9, 18, 0.83);
console.log(result);

I would use range-inclusive from npm in an actual project. It even supports backwards steps, so that's cool.

Ruslan López
  • 4,433
  • 2
  • 26
  • 37
m59
  • 43,214
  • 14
  • 119
  • 136
50

I highly recommend underscore or lo-dash libraries:

http://underscorejs.org/#range

(Almost completely compatible, apparently lodash runs quicker but underscore has better doco IMHO)

_.range([start], stop, [step])

Both libraries have bunch of very useful utilities.

ErichBSchulz
  • 15,047
  • 5
  • 57
  • 61
34

My version of the loop ;)

var lowEnd = 1;
var highEnd = 25;
var arr = [];
while(lowEnd <= highEnd){
   arr.push(lowEnd++);
}
Pavel Podlipensky
  • 8,201
  • 5
  • 42
  • 53
26

fastest way

  1. while-- is faster on most browsers
  2. direct setting a variable is faster than push

function:

var x=function(a,b,c,d){d=[];c=b-a+1;while(c--){d[c]=b--}return d},

theArray=x(lowEnd,highEnd);

or

var arr=[],c=highEnd-lowEnd+1;
while(c--){arr[c]=highEnd--}

EDIT

readable version

var arr = [],
c = highEnd - lowEnd + 1;
while ( c-- ) {
 arr[c] = highEnd--
}

Demo

http://jsfiddle.net/W3CUn/

FOR THE DOWNVOTERS

performance

http://jsperf.com/for-push-while-set/2

faster in ie and 3x faster in firefox

only on aipad air the for loop is a little faster.

tested on win8, osx10.8, ubuntu14.04, ipad, ipad air, ipod;

with chrome,ff,ie,safari,mobile safari.

i would like to see the performance on older ie browsers where the for loop isn't that optimized!

cocco
  • 16,442
  • 7
  • 62
  • 77
  • 6
    These are great ideas... but I would try and make your code more easily readable for others with proper indenting, word spacing, and line returns.. – Blaine Kasten Sep 24 '13 at 16:33
  • As this are very short functions with not manyparameters i intendendly wrote it this way so you just can copy and past.in the first case just replace x with whatever function name you want.there is also noo need to change the functions abcd as they are only that functions private parameters. – cocco Sep 24 '13 at 17:09
  • And c & d are put inside the functions parameters as placeholder to leave out the 'var' – cocco Sep 24 '13 at 17:15
  • All these performance concerns are beside the point. The OP asked how to do it, not for a hand-minified implementation. This is difficult to reason about in its current form, and is hard to learn from. – Phil Aug 27 '22 at 10:05
11
function range(j, k) { 
    return Array
        .apply(null, Array((k - j) + 1))
        .map(function(_, n){ return n + j; }); 
}

this is roughly equivalent to

function range(j, k) { 
    var targetLength = (k - j) + 1;
    var a = Array(targetLength);
    var b = Array.apply(null, a);
    var c = b.map(function(_, n){ return n + j; });
    return c;
}

breaking it down:

var targetLength = (k - j) + 1;

var a = Array(targetLength);

this creates a sparse matrix of the correct nominal length. Now the problem with a sparse matrix is that although it has the correct nominal length, it has no actual elements, so, for

j = 7, k = 13

console.log(a);

gives us

Array [ <7 empty slots> ]

Then

var b = Array.apply(null, a);

passes the sparse matrix as an argument list to the Array constructor, which produces a dense matrix of (actual) length targetLength, where all elements have undefined value. The first argument is the 'this' value for the the array constructor function execution context, and plays no role here, and so is null.

So now,

 console.log(b);

yields

 Array [ undefined, undefined, undefined, undefined, undefined, undefined, undefined ]

finally

var c = b.map(function(_, n){ return n + j; });

makes use of the fact that the Array.map function passes: 1. the value of the current element and 2. the index of the current element, to the map delegate/callback. The first argument is discarded, while the second can then be used to set the correct sequence value, after adjusting for the start offset.

So then

console.log(c);

yields

 Array [ 7, 8, 9, 10, 11, 12, 13 ]
david.barkhuizen
  • 5,239
  • 4
  • 36
  • 38
  • 4
    Thank you for posting an answer to this question! Code-only answers are discouraged on Stack Overflow, because it can be difficult for the original poster (or future readers) to understand the logic behind them. Please, edit your question and include an explanation of your code so that others can benefit from your answer. Thanks! – Maximillian Laumeister Sep 17 '15 at 18:17
  • 1
    @MaximillianLaumeister annotated – david.barkhuizen Sep 18 '15 at 07:09
  • 1
    This is a great answer now! – jcuenod May 27 '16 at 23:13
  • Just a suggestion, but '_' (an underscore) seems to be the common name for discarded/unused parameters. – Astravagrant Oct 19 '17 at 07:59
7

My five cents:

Both direction array of integers function.

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

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

Based on this answer.

function range(start, end) {
  const isReverse = (start > end);
  const targetLength = isReverse ? (start - end) + 1 : (end - start ) + 1;
  const arr = new Array(targetLength);
  const b = Array.apply(null, arr);
  const result = b.map((discard, n) => {
    return (isReverse) ? n + end : n + start;
  });

  return (isReverse) ? result.reverse() : result;
}

P.S. For use in real life you should also check args for isFinite() and isNaN().

S Panfilov
  • 16,641
  • 17
  • 74
  • 96
7

Solution with pure ES6

Inspired by m59's answer above, but without the dependency on fill:

const range = (start, stop) => Array.from({ length: stop - start + 1 }, (_, i) => start + i)

So you can use it like:

range(3,5)
=> [3, 4, 5]
Flavio Wuensche
  • 9,460
  • 1
  • 57
  • 54
6

If the start is always less than the end, we can do:

function range(start, end) {
  var myArray = [];
  for (var i = start; i <= end; i += 1) {
    myArray.push(i);
  }
  return myArray;
};
console.log(range(4, 12));                 // → [4, 5, 6, 7, 8, 9, 10, 11, 12]

If we want to be able to take a third argument to be able to modify the step used to build the array, and to make it work even though the start is greater than the end:

function otherRange(start, end, step) {
  otherArray = [];
  if (step == undefined) {
    step = 1;
  };
  if (step > 0) {
    for (var i = start; i <= end; i += step) {
      otherArray.push(i);
    }
  } else {
    for (var i = start; i >= end; i += step) {
      otherArray.push(i);
    }
  };
  return otherArray;
};
console.log(otherRange(10, 0, -2));        // → [10, 8, 6, 4, 2, 0]
console.log(otherRange(10, 15));           // → [10, 11, 12, 13, 14, 15]
console.log(otherRange(10, 20, 2));        // → [10, 12, 14, 16, 18, 20]

This way the function accepts positive and negative steps and if no step is given, it defaults to 1.

drjorgepolanco
  • 7,479
  • 5
  • 46
  • 47
6
function createNumberArray(lowEnd, highEnd) {
    var start = lowEnd;
    var array = [start];
    while (start < highEnd) {
        array.push(start);
        start++;
    }
} 
Igor
  • 33,276
  • 14
  • 79
  • 112
  • 2
    `var array = {start};` gives you a standard object which doesn't have the `push` method. you mean `var array = [];` surely – meouw Nov 09 '11 at 18:02
3
var values = $(this).val().split('-'),
    i = +values[0],
    l = +values[1],
    range = [];

while (i < l) {
    range[range.length] = i;
    i += 1;
}

range[range.length] = l;

There's probably a DRYer way to do the loop, but that's the basic idea.

sdleihssirhc
  • 42,000
  • 6
  • 53
  • 67
3

You can design a range method that increments a 'from' number by a desired amount until it reaches a 'to' number. This example will 'count' up or down, depending on whether from is larger or smaller than to.

Array.range= function(from, to, step){
    if(typeof from== 'number'){
        var A= [from];
        step= typeof step== 'number'? Math.abs(step):1;
        if(from> to){
            while((from -= step)>= to) A.push(from);
        }
        else{
            while((from += step)<= to) A.push(from);
        }
        return A;
    }   
}

If you ever want to step by a decimal amount : Array.range(0,1,.01) you will need to truncate the values of any floating point imprecision. Otherwise you will return numbers like 0.060000000000000005 instead of .06.

This adds a little overhead to the other version, but works correctly for integer or decimal steps.

Array.range= function(from, to, step, prec){
    if(typeof from== 'number'){
        var A= [from];
        step= typeof step== 'number'? Math.abs(step):1;
        if(!prec){
            prec= (from+step)%1? String((from+step)%1).length+1:0;
        }
        if(from> to){
            while(+(from -= step).toFixed(prec)>= to) A.push(+from.toFixed(prec));
        }
        else{
            while(+(from += step).toFixed(prec)<= to) A.push(+from.toFixed(prec));
        }
        return A;
    }   
}
kennebec
  • 102,654
  • 32
  • 106
  • 127
2

Here's 3 functions that should cover everything I could think of (including fixes for problems in some other answers): rangeInt(), range(), and between(). Both ascending and descending orders are accounted for in all cases.

Examples

rangeInt()

Includes endpoints and only deals with integers

rangeInt(1, 4)  // [1, 2, 3, 4] Ascending order
rangeInt(5, 2)  // [5, 4, 3, 2] Descending order
rangeInt(4, 4)  // [4]          Singleton set (i.e. not [4, 4])
rangeInt(-1, 1) // [-1, 0, 1]   Mixing positive and negative

range()

Same as rangeInt() except

  1. Not limited to integers
  2. Allows for a specified number of points in a third parameter
range(0, 10, 2)  // [0, 3.333, 6.666, 10] Gets endpoints and 2 points between
range(0, 1.5, 1) // [0, 0.75, 1.5]        Accepts fractions

between()

Same as range() except

  1. Endpoints are excluded
  2. There are no singleton sets (an empty array will be returned instead)
between(0, 10, 2) // [3.333, 6.666]
between(-1, -1.5) // [-1.25]
between(4, 4, 99) // []

Source

/**
 * Gets a set of integers that are evenly distributed along a closed interval
 * @param {int} begin - Beginning endpoint (inclusive)
 * @param {int} end   - Ending endpoint (inclusive)
 * @return {Array} Range of integers
 */
function rangeInt( begin, end )  {
    if ( !Number.isInteger(begin) || !Number.isInteger(end) ) {
        throw new Error('All arguments must be integers')
    }
    return range(begin, end, Math.abs(end - begin) - 1)
}

/**
 * Gets a set of numbers that are evenly distributed along a closed interval
 * @param {Number} begin  - Beginning endpoint (inclusive)
 * @param {Number} end    - Ending endpoint (inclusive)
 * @param {int}    points - How many numbers to retrieve from the open interval
 * @return {Array} Range of numbers
 */
function range( begin, end, points ) {
    if ( begin !== end ) {
        return [ begin, ...between(begin, end, points), end ]
    }
    else if ( Number.isFinite(begin) ) {
        return [ begin ] // singleton set
    }
    else throw new Error('Endpoints must be finite')
}

/**
 * Gets a subset of numbers that are evenly distributed along an open interval
 * @param {Number} begin  - Beginning endpoint (exclusive)
 * @param {Number} end    - Ending endpoint (exclusive)
 * @param {int}    points - How many numbers to retrieve from the interval
 * @return {Array} Retrieved numbers
 */
function between( begin, end, points = 1 ) {
    if ( !Number.isFinite(begin) || !Number.isFinite(end) || !Number.isFinite(points) ) {
        throw new Error('All arguments must be finite')
    }
    const set = []
    // Skip if an open interval does not exist
    if ( begin !== end ) {
        const step = (end - begin) / (points + 1)
        for ( let i = 0; i < points; i++ ) {
            set[i] = begin + (i + 1) * step
        }
    }
    return set
}
Leon Williams
  • 674
  • 1
  • 7
  • 15
1

Adding http://minifiedjs.com/ to the list of answers :)

Code is similar to underscore and others:

var l123 = _.range(1, 4);      // same as _(1, 2, 3)
var l0123 = _.range(3);        // same as _(0, 1, 2)
var neg123 = _.range(-3, 0);   // same as _(-3, -2, -1)
var empty = _.range(2,1);      // same as _()

Docs here: http://minifiedjs.com/api/range.html

I use minified.js because it solves all my problems with low footprint and easy to understand syntax. For me, it is a replacement for jQuery, MustacheJS and Underscore/SugarJS in one framework.

Of course, it is not that popular as underscore. This might be a concern for some.

Minified was made available by Tim Jansen using the CC-0 (public domain) license.

Christian
  • 7,062
  • 5
  • 36
  • 39
1
const range = (start, stop, step) => 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

Saber
  • 2,440
  • 1
  • 25
  • 40
1

You can do that in one line in ES6

const start = 5; // starting number
const end = 10; // ending number

const arr = Array.from({ length: end - start + 1 }, (_, i) => start + i);

console.log(arr); // [5, 6, 7, 8, 9, 10]
Muho
  • 3,188
  • 23
  • 34
0
_Array = (length) => Object.keys(Array.from({length}))

//_Array = [0, 1, 2, 3, 4]
metodribic
  • 1,561
  • 17
  • 27
Herald
  • 1
  • 1
0

const range = (start: number, end: number) => {
  for (var i = start, list = []; i <= end; list.push(i), i++);
  return list;
};
David Lopes
  • 227
  • 2
  • 10
0

Hope the below method will help someone. Here count variable can be used to mention the array length.

const generateRandomArryOfNumbers = (min = 1, max = 100, count = 31) => {
  return Array.from(new Array(count), () =>
    Math.floor(Math.random() * (max - min + 1) + min)
  );
};
Umesh Naik
  • 99
  • 2
  • 8
0

Typescript version:

function getAllNumbersBetween(start: number, end: number) {
  var numbers: number[] = [];

  for (var i = start; i < end; i++) {
    numbers.push(i);
  }

  return numbers;
}
zLupim
  • 299
  • 3
  • 15
-1

Solving in underscore

data = [];
_.times( highEnd, function( n ){ data.push( lowEnd ++ ) } );
vladiim
  • 1,862
  • 2
  • 20
  • 27
-1

        function getRange(a,b)
        {
            ar = new Array();
            var y = a - b > 0 ? a - b : b - a;
            for (i=1;i<y;i++)
            {
                ar.push(i+b);
            }
            return ar;
        }
Mamdouh
  • 1
  • 4
  • This will actually produce incorrect results for a > b, e.g. getRange (5, 1) - it will produce [1,2,3,4,5] but should [5,4,3,2,1] – Andrey Dec 21 '21 at 02:23
-1

After testing and adjusting all the pure js solutions above, I offer you the following solution, based on the fastest algo offered, and compatible with the python range.

The js version is even better, since it supports decimals.

function range(start, end, step=1) {
    if (typeof end === 'undefined') {
        end = start, start = 0;
    }
    let len = Math.round((end - start) / step);
    let arr = [];
    while ( len-- ) {
        arr[len] = start + (len * step);
    }
    return arr;
}
console.log(range(9, 18, 0.83));
/* [
  9,
  9.83,
  10.66,
  11.49,
  12.32,
  13.149999999999999,
  13.98,
  14.809999999999999,
  15.64,
  16.47,
  17.299999999999997
] */
console.log(range(9, 18, 2)); // [9, 11, 13, 15, 17]
console.log(range(9, 18)); // [9, 10, 11, 12, 13, 14, 15, 16, 17]
console.log(range(9)); // [0, 1, 2, 3, 4, 5, 6, 7, 8]

see the python code, for integers only:

print(list(range(9, 18, 2))); # [9, 11, 13, 15, 17]
print(list(range(9, 18))); # [9, 10, 11, 12, 13, 14, 15, 16, 17]
print(list(range(9))); # [0, 1, 2, 3, 4, 5, 6, 7, 8]
alex
  • 651
  • 1
  • 9
  • 11