151

Is there a function in JavaScript similar to Python's range()?

I think there should be a better way than to write the following lines every time:

array = new Array();
for (i = 0; i < specified_len; i++) {
    array[i] = i;
}
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
clwen
  • 20,004
  • 31
  • 77
  • 94
  • 1
    @clwen: Unfortunately there is not, but take a look at my code - I have written a function that is aimed at emulating the way `range()` works in Python, so you can use it. There is no such function in JavaScript, but there are some plugins for different frameworks, such as [`Range` class for MooTools](http://mootools.net/forge/p/range). – Tadeck Nov 25 '11 at 19:06
  • Also have a look at the [implementation of `d3.range()`](https://github.com/d3/d3-array/blob/v3.2.2/src/range.js) – djvg Feb 15 '23 at 11:10

32 Answers32

201

For a very simple range in ES6:

let range = n => Array.from(Array(n).keys())

From bigOmega's comment, this can be shortened using Spread syntax:

let range = n => [...Array(n).keys()]
Will Ediger
  • 893
  • 9
  • 17
  • 52
    A simpler version of this is `let range = n => [...Array(n).keys()]` – bigOmega ツ Sep 13 '17 at 12:13
  • 2
    @BharathRaja great, thanks! Why not const? I'll try to use const wherever I can :) like the Java final counterpart ;) – Kjellski Mar 13 '18 at 11:17
  • You're right, I try to use `const` as much as possible, but here it'll just be a reference to the array, so the array would still be editable :'D – bigOmega ツ Mar 21 '18 at 08:44
  • 1
    @bigOmega The `const` would apply to the function itself, not its return value. You probably don't want to modify the function in any way. – Solomon Ucko Jun 08 '19 at 12:32
  • 16
    This answer does not account for a starting index and the ability to increase step size. – Fluous Aug 24 '19 at 11:36
  • I'm new to js and was looking to emulate Python's `range(start, stop)`. Here's one way I found, building on top of this answer: `let range = (start, stop) => [...Array(stop).keys()].slice(start);` – joseville Apr 09 '22 at 17:57
  • What's wrong with `const range = n -> Array(n).keys();` ? (ignoring the issue of start index and step size) – Don Hatch May 19 '23 at 09:12
123

No, there is none, but you can make one.

JavaScript's implementation of Python's range()

Trying to emulate how it works in Python, I would create function similar to this:

function range(start, stop, step) {
    if (typeof stop == 'undefined') {
        // one param defined
        stop = start;
        start = 0;
    }

    if (typeof step == 'undefined') {
        step = 1;
    }

    if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
        return [];
    }

    var result = [];
    for (var i = start; step > 0 ? i < stop : i > stop; i += step) {
        result.push(i);
    }

    return result;
};

See this jsfiddle for a proof.

Comparison between range() in JavaScript and Python

It works in the following way:

  • range(4) returns [0, 1, 2, 3],
  • range(3,6) returns [3, 4, 5],
  • range(0,10,2) returns [0, 2, 4, 6, 8],
  • range(10,0,-1) returns [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
  • range(8,2,-2) returns [8, 6, 4],
  • range(8,2) returns [],
  • range(8,2,2) returns [],
  • range(1,5,-1) returns [],
  • range(1,5,-2) returns [],

and its Python counterpart works exactly the same way (at least in the mentioned cases):

>>> range(4)
[0, 1, 2, 3]
>>> range(3,6)
[3, 4, 5]
>>> range(0,10,2)
[0, 2, 4, 6, 8]
>>> range(10,0,-1)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> range(8,2,-2)
[8, 6, 4]
>>> range(8,2)
[]
>>> range(8,2,2)
[]
>>> range(1,5,-1)
[]
>>> range(1,5,-2)
[]

So if you need a function to work similarly to Python's range(), you can use above mentioned solution.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
Tadeck
  • 132,510
  • 28
  • 152
  • 198
  • 4
    maybe a couple of additional defensive checks - ensure that the arguments passed are all coercible to numbers and ensure that `stop` is greater than `start` (and swap them if not). – Russ Cam Nov 25 '11 at 18:46
  • 1
    @RussCam: Thanks for pointing this out. I did not add defensive checks for types etc., but I implemented reverse order of elements - it now works exactly the same as Python counterpart, when the last param is negative integer. – Tadeck Nov 25 '11 at 18:59
  • @RussCam: `start >= stop` leading to an empty array is necessary if the goal is really emulating Python's range. And I'd argue it's more intuitive anyway. –  Nov 25 '11 at 19:11
  • 1
    @delnan: Check may be more complex, as simple `start >= stop` is not enough for this function to behave like `range()` in Python. I have updated my answer. – Tadeck Nov 25 '11 at 19:19
  • @delnan - I'm not familiar with the Python implementation. I guess if it's only going to be used by peeps familiar with the Python implementation that it makes sense to emulate it :) – Russ Cam Nov 25 '11 at 19:27
  • @RussCam: You are probably right :) `range()` in Python is very useful, but indeed it is just a different language and it may be less useful in JavaScript. It all depends on the specific case. – Tadeck Nov 25 '11 at 19:33
  • Also, make sure that ```0``` as ```step``` will be rejected not to run out of heap. – imrek Jul 02 '16 at 08:26
  • @DrunkenMaster: In such case current JS approach will return empty array (`[]`). If you have a proposal on how to approach it, feel free to suggest edits. I would like [`RangeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError) to be used for raising exception. – Tadeck Jul 05 '16 at 15:20
  • @Tadeck It's only going to return ```[]``` if ```stop``` is not less than ```start```. so, e.g. ```range(1, -10, 0)``` is going to make the function run out of memory. Python rejects ```0``` for ```step``` with ```ValueError: range() arg 3 must not be zero```, since JS does not have that many built-in error types and RangeError is semantically the closest, it would be adequate to throw. – imrek Jul 05 '16 at 16:19
  • Unfortunately this takes a lot of memory when I use this for a 'for' statement. – Chris van Chip Jun 26 '19 at 11:09
  • For TypeScript: `function range(start: number, stop?: number, step?: number)` – echefede Aug 14 '19 at 12:41
  • This answer fails to mention a fatal flaw with its implementation - eager evaluation. Python 3's `range()` has always been lazily evaluated. On my computer, `len(range(1000000000))` evaluates instantaneously because no list is ever created - `range()` returns a generator (python 2's `range()` did create a list). Loops using this answer's code require O(n) memory where n is the number of iterations. Since this answer was written, JavaScript introduced generator functions, which have been supported by major browsers since about 2014. See @janka102's answer for an example of how to use them. – asky Mar 05 '20 at 12:46
44

Fusing together both answers from @Tadeck and @georg, I came up with this:

function* range(start, stop, step = 1) {
    if (stop == null) {
        // one param defined
        stop = start;
        start = 0;
    }

    for (let i = start; step > 0 ? i < stop : i > stop; i += step) {
        yield i;
    }
}

To use it in a for loop you need the ES6/JS1.7 for-of loop:

for (let i of range(5)) {
    console.log(i);
}
// Outputs => 0 1 2 3 4

for (let i of range(0, 10, 2)) {
    console.log(i);
}
// Outputs => 0 2 4 6 8

for (let i of range(10, 0, -2)) {
    console.log(i);
}
// Outputs => 10 8 6 4 2
janka102
  • 979
  • 1
  • 8
  • 16
  • Why not using [default parameters](http://es6-features.org/#DefaultParameterValues) if you are using ES6? – Amin NAIRI Apr 30 '17 at 10:20
  • @Gradiuss that would work for the `step` parameter, but when `stop` is not passed in, both `start` and `stop` need to be changed. I'll update it – janka102 May 01 '17 at 16:33
  • 3
    WTG, this is the best implementation presented so far. It uses generators (good, since there's no need to store the whole sequence in memory) and is very succint. – Lucio Paiva May 28 '17 at 02:26
  • undefined is a pointer to an object like null. possible to compare with 3 equal signs like: if (stop === undefined) { 3 equals signs is compare without auto casting. compare as is also compare type. 2 equal signs is compare with auto casting to other side type. – Shimon Doodkin Mar 27 '18 at 12:48
34

2018: this answer keeps getting upvotes, so here's an update. The code below is obsolete, but luckily ES6 standardized generators and the yield keyword, and they are universally supported across platforms. An example of the lazy range() using yield can be found here.


In addition to what's already said, Javascript 1.7+ provides support for iterators and generators which can be used to create a lazy, memory-efficient version of range, simlar to xrange in Python2:

function range(low, high) {  
    return {
        __iterator__: function() {
            return {  
                next: function() {
                    if (low > high)
                        throw StopIteration;  
                    return low++;
                }
            }
        }
    }
}

for (var i in range(3, 5))  
  console.log(i); // 3,4,5
georg
  • 211,518
  • 52
  • 313
  • 390
  • 1
    +1 Great idea! Could you implement also `step` argument and test it on the values from [my answer](http://stackoverflow.com/a/8273091/548696)? Your answer is great for the applications where we have very specific browsers in mind (it won't work in Google Chrome, Safari and IE version earlier than 9: http://stackoverflow.com/a/2209743/548696). – Tadeck Sep 09 '12 at 03:18
  • @Tadeck: ironically, I asked a [very similar question](http://stackoverflow.com/q/12173856/989121) recently, check it out - some good answers there. BTW, your code does not pass my test ;( – georg Sep 09 '12 at 11:14
  • Could you share the test data and expected results? I would be happy to improve it, but my tests are 100% passing. Are you saying the code I have given is not properly parsed by script you have placed in this question: http://stackoverflow.com/q/12173856/548696 ? – Tadeck Sep 09 '12 at 17:21
  • @Tadeck: nevermind. I tested slices and your code is for ranges. – georg Sep 09 '12 at 19:59
  • 1
    Python's `range` has "last" value _excluded_ (so one needs to use `>=` instead of `>` in the above code) – Pac0 Jul 17 '20 at 08:13
28

A port of the range function from Python 2 is provided by the underscore.js and lodash utility libraries (along with many other useful tools). Examples copied from the underscore docs:

_.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);
=> []
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
22

Can be achieved by attaching an iterator to the Number prototype

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

[...5] // will result in [0,1,2,3,4,5]

Taken from Kyle Simpson's course Rethinking Asynchronous JavaScript

MCH
  • 986
  • 13
  • 19
11

Here's a small extension for one of the answers in case you need to specify both starting and ending position of the range:

let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
Dmitrii Mikhailov
  • 5,053
  • 7
  • 43
  • 69
7

pythonic mimics the Python range behaviour best it can using JS' generators (yield), supporting both the range(stop) and range(start, stop, step) use cases. In addition, pythonic's range function returns an Iterator object similar to Python that supports map and filter, so one could do fancy one-liners like:

import {range} from 'pythonic';
// ...
const results = range(5).map(wouldBeInvokedFiveTimes);
// `results` is now an array containing elements from
// 5 calls to wouldBeInvokedFiveTimes

Install using npm:

npm install --save pythonic

Disclosure I'm author and maintainer of Pythonic

Keyvan
  • 813
  • 9
  • 19
7

Here you go.

This will write (or overwrite) the value of each index with the index number.

Array.prototype.writeIndices = function( n ) {
    for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
    return this;
};

If you don't provide a number, it will use the current length of the Array.

Use it like this:

var array = [].writeIndices(10);  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
RightSaidFred
  • 11,209
  • 35
  • 35
6

Further refined with ES6 default parameters.

let range = function*(start = 0, stop, step = 1) {
  let cur = (stop === undefined) ? 0 : start;
  let max = (stop === undefined) ? start : stop;
  for (let i = cur; step < 0 ? i > max : i < max; i += step)
    yield i
}
Volv
  • 63
  • 1
  • 6
6

The following is a natural adaption of Python's range() function to JavaScript:

// Generate range from start (inclusive) to stop (exclusive):
function* range(start, stop, step = 1) {
   if (stop === undefined) [start, stop] = [0, start];
   if (step > 0) while (start < stop) yield start, start += step;
   else if (step < 0) while (start > stop) yield start, start += step;
   else throw new RangeError('range() step argument invalid');
} 

// Examples:
console.log([...range(3)]);       // [0, 1, 2]
console.log([...range(0, 3)]);    // [0, 1, 2]
console.log([...range(0, 3, -1)]);// []
console.log([...range(0, 0)]);    // []
console.log([...range(-3)]);      // []
console.log([...range(-3, 0)]);   // [-3, -2, -1]

It supports any argument which can be compared to 0 and stop and can be incremented by step. It behaves identical to the Python version when used with numbers not exceeding Number.MAX_SAFE_INTEGER.

Please note the following corner cases:

[...range(0, 0, 0)];        // RangeError: range() step argument invalid
[...range(Number.MAX_SAFE_INTEGER + 1, Number.MAX_SAFE_INTEGER + 2)];  // []
[...range(Number.MAX_SAFE_INTEGER + 2, Number.MAX_SAFE_INTEGER + 3)];  // Infinite loop
[...range(0.7, 0.8, 0.1)];  // [0.7, 0.7999999999999999]
[...range('1', '11')];      // ['1']
[...range('2', '22')];      // Infinite loop

In contrast to @Tadeck's, @Volv's and @janka102's answer which return [], undefined or enter an infinite loop when step evaluates to 0 or NaN, this generator function throws an exception similar to Python's behavior.

Community
  • 1
  • 1
le_m
  • 19,302
  • 9
  • 64
  • 74
  • 1
    Agreed. Although the other answers are elegant in their own way, this approach and functionality is much more pythonic. – Travis Clarke Mar 18 '18 at 07:33
6

For anyone looking for a modern solution [...Array(n).keys()]

Tesohh
  • 111
  • 1
  • 6
5

For getting an array of size x, here's an one-liner without using any library

var range = n => Array(n + 1).join(1).split('').map((x, i) => i)

works as

> range(4)
[0, 1, 2, 3]
bigOmega ツ
  • 371
  • 3
  • 13
5

MDN recommends this approach: Sequence generator (range)

// Sequence generator function (commonly referred to as "range", e.g. Clojure, PHP etc)
const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));

// Generate numbers range 0..4
console.log("range(0, 4, 1):", range(0, 4, 1));
// [0, 1, 2, 3, 4] 

// Generate numbers range 1..10 with step of 2 
console.log("\nrange(1, 10, 2):", range(1, 10, 2));
// [1, 3, 5, 7, 9]

// Generate the alphabet using Array.from making use of it being ordered as a sequence
console.log("\nrange('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x))", range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x)));
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
Micah J
  • 68
  • 5
IliasT
  • 3,973
  • 1
  • 24
  • 26
4

Actually, in Python range() returns an iterable object and we know that iterators are more memory efficient than arrays (or lists in Python). So if we want to implement the same concept with exact functionality in JavaScript we can use an iterator object:

class range {

constructor(start, stop, step = 1) {
    //check for invalid input
    if (stop !== undefined && typeof stop !== 'number'
        || typeof start !== 'number'
        || typeof step !== 'number') {
        throw Error('invalid input for range function');
    }

    //check if second argument is provided
    if (stop === undefined) {
        stop = start;
        start = 0;
    }

    //initialize the object properties
    this.start = start;
    this.stop = stop;
    this.step = step;
}

//create the iterator object with Symbol.iterator
[Symbol.iterator]() {
    return {
        current: this.start,
        last: this.stop,
        step: this.step,
        //implement the next() method of the iterator
        next() {
            if (this.step === 0) {
                return { done: true };
            } else if (this.step > 0 ? this.current < this.last : this.current > this.last) {
                let value = this.current;
                this.current += this.step;
                return { done: false, value };
            } else {
                return { done: true };
            }
        }
    };
};
}

and for example we have:

for (const num of new range(1, 10, 2)) {
console.log(num);
}

also we can create an array easily:

let arr = [...new range(10, -5, -1)];

or:

let arr = Array.from(new range(10));
Mohammad
  • 61
  • 3
3

Is there a function in JavaScript similar to Python's range()?

All of the solutions here are referring to Python 2's range (probably because of the code example you gave). However in Python 3, the range() method returns an iterator. JavaScript also has iterators and they're more space efficient than generating the whole array and storing it in memory.

So the more accurate representation of Python 3's range(n) function is Array(n).keys().

For example:

for (let i of Array(n).keys()) {
  console.log(i) // 0, 1, 2, 3, ..., n
}

One more example (which has already been covered in the other answers). Converting the iterator to an array (ES6):

let ary = [...Array(n).keys()];
// ary = [0, 1, 2, 3, ..., n]
MattCochrane
  • 2,900
  • 2
  • 25
  • 35
2

You may use underscore library. It contains dozens of useful functions for working with arrays and many more.

Radagast
  • 5,798
  • 3
  • 22
  • 18
2

Still no built-in function that is equivalent to range(), but with the most recent version - ES2015 - you can build your own implementation. Here's a limited version of it. Limited because it doesn't take into account the step parameter. Just min, max.

const range = (min = null, max = null) =>
  Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)

This is accomplished by the Array.from method able to build an array from any object that has a length property. So passing in a simple object with just the length property will create an ArrayIterator that will yield length number of objects.

zmag
  • 7,825
  • 12
  • 32
  • 42
Steve Brownlee
  • 113
  • 1
  • 6
2

This is my preferred way. It allows you to specify one or two inputs like in Python.

function range(start, end) {
  return Array.from(Array(end||start).keys()).slice(!!end*start)
}
Rob Kwasowski
  • 2,690
  • 3
  • 13
  • 32
1

Assuming you need a simple range with a single step:

let range = (start, end)=> {
    if(start === end) return [start];
    return [start, ...range(start + 1, end)];
}

else

let range = (start, end, step)=> {
    if(start === end) return [start];
    return [start, ...range(start + step, end, step)];
}

refer to here for more.

J_Zar
  • 2,034
  • 2
  • 21
  • 34
N Djel Okoye
  • 950
  • 12
  • 10
1

Is there a function in JavaScript similar to Python's range()?

As answered before: no, there's not. But you can make your own. I believe this is an interesting approach for ES6. It works very similar to Python 2.7 range(), but it's much more dynamic.

function range(start, stop, step = 1) 
{
    // This will make the function behave as range(stop)
    if(arguments.length === 1)
    {
        return [...Array(arguments[0]).keys()]
    }

    // Adjusts step to go towards the stop value
    if((start > stop && !(step < 0)) ||
       (start < stop && !(step > 0)))
    {
        step *= -1
    }

    let returnArray = []
    // Checks if i is in the interval between start and stop no matter if stop
    // is lower than start or vice-versa
    for(let i = start; (i-start)*(i-stop) <= 0; i += step)
    {
        returnArray.push(i)
    }
    return returnArray
}

This function can behave in three different ways (just like Python's range()):

  1. range(stop)
  2. range(start, stop)
  3. range(start, stop, step)

These examples:

console.log(range(5))
console.log(range(-2, 2))
console.log(range(2, -2))
console.log(range(10, 20, 2))

Will give you the following output:

[ 0, 1, 2, 3, 4 ]
[ -2, -1, 0, 1, 2 ]
[ 2, 1, 0, -1, -2 ]
[ 10, 12, 14, 16, 18, 20 ]

Note that instead of iterating over the array with the in operator (like python), you have to use of. Thus the i variable assumes the value, and not the index, of the array's element.

for(let i of range(5))
{
    // do something with i...
}
sandmann
  • 363
  • 2
  • 13
1

An option for NodeJs is to use a Buffer:

[...Buffer.alloc(5).keys()]
// [ 0, 1, 2, 3, 4 ]

What's nice is that you can iterate directly on the buffer:

Buffer.alloc(5).forEach((_, index) => console.log(index))
// 0
// 1
// 2
// 3
// 4

You can't do that with an uninitialized Array:

Array(5).forEach((_, index) => console.log(index))
// undefined

But, who in their right mind uses a Buffer for a purpose like this ;)

Otto
  • 1,787
  • 1
  • 17
  • 25
1
function range(start, stop) {
    if (typeof stop == 'undefined') {
        stop = start;
        start = 0;
    }
   
    result = [...Array(stop).keys()].slice(start, stop);
    return result;
}
MSA
  • 249
  • 5
  • 10
0

Here is another es6 implementation of the range

// range :: (from, to, step?) -> [Number]
const range = (from, to, step = 1) => {
  //swap values if necesery
  [from, to] = from > to ? [to, from] : [from, to]
  //create range array
  return [...Array(Math.round((to - from) / step))]
    .map((_, index) => {
      const negative = from < 0 ? Math.abs(from) : 0
      return index < negative ? 
        from + index * step  :
        (index - negative + 1) * step
    })
}  

range(-20, 0, 5)
  .forEach(val => console.log(val))

for(const val of range(5, 1)){
   console.log(`value ${val}`)
}
0

No, there is none, but you can make one.

I'm partial to Python3 behavior of range. You will find below JavaScript's implementation of Python's range():

function* range(start=0, end=undefined, step=1) {    
    if(arguments.length === 1) {end = start, start = 0}    
    
    [...arguments].forEach(arg => {    
        if( typeof arg !== 'number') {throw new TypeError("Invalid argument")}                               
    })    
    if(arguments.length === 0) {throw new TypeError("More arguments neede")}    
        
    if(start >= end) return                                                                                                                                     
    yield start    
    yield* range(start + step, end, step)    
}    
         
// Use Cases
console.log([...range(5)])

console.log([...range(2, 5)])

console.log([...range(2, 5, 2)])
console.log([...range(2,3)])
// You can, of course, iterate through the range instance.
elayira
  • 1
  • 1
0

Here's how i do it

let n = 5 
[...Array(n).keys()].map(x=>{console.log(x)})

output

0
1
2
3
4
Ricky Sahu
  • 23,455
  • 4
  • 42
  • 32
0
/**
 * range generator
 *
 * @param {Integer} start - Optional. An integer specifying at which position to start. Default is 0
 * @param {Integer} stop  - Required. An integer specifying at which position to stop. Excluded.
 * @param {Integer} step  - Optional. An integer specifying the incrementation. Default is 1
 */

function* range (start, stop, step = 1) {

  if (arguments.length === 1) { [start, stop] = [0, start]; }

  if (![start, stop, step].every(Number.isInteger)) { throw new TypeError('range needs integer arguments'); }

  if ((start - stop) * step >= 0) { return []; }

  let check = start > stop ? (a, b) => a > b : (a, b) => a < b;
  while (check(start, stop)) { yield start, start += step; }
}

console.log([...range(4)]);
console.log([...range(2, 4)]);
console.log([...range(1, 4, 2)]);
console.log([...range(-4, -1, 1)]);
console.log([...range(10, 4, -2)]);
console.log([...range(-1, -4, -1)]);
mh-firouzjah
  • 834
  • 1
  • 6
  • 15
0

A simple approach in Typescript without error checking. Up and down incl. steprate.

const range = (start: number, end: number | null = null, step: number = 1): number[] =>
  [...Array(end === null ? start : Math.abs(end - start)).keys()]
    .filter((n: number): boolean => n % step === 0)
    .map((n: number): number => (end === null ? n : end < start ? Math.max(start, end) - n : n + start));

Same in Javascript ES6

const range = (start, end = null, step = 1) =>
  [...Array(end === null ? start : Math.abs(end - start)).keys()]
    .filter((n) => n % step === 0)
    .map((n) => (end === null ? n : end < start ? Math.max(start, end) - n : n + start));
Denis Giffeler
  • 1,499
  • 12
  • 21
0
const range = function*(start, stop, inclusive=false) {
    let dx = Math.sign(stop - start);
    if (inclusive) stop += dx;
    for (let x = start; x !== stop; x += dx) yield x;
}

const arange = (start, stop, inclusive) => [...range(start, stop, inclusive)];
The Thonnu
  • 3,578
  • 2
  • 8
  • 30
maru
  • 11
  • 2
0

A bit of concise, inclusive es6 fun. Codepen demo

var rng=(s,e=null,d=1)=>{
  if(e==null)var[s,e]=[0,s]//missing e? s is e
  if(s>e)d=d<0?d:-d//s,e backwards? might flip sign
  return[...Array(((e-s)/d+1) << 0).keys()].map(x=>d*x+s)
}

rng(3) -> [0,1,2,3]
rng(0,2) -> [0,1,2]
rng(4,6) -> [4,5,6]
rng(3,9,3) -> [3,6,9]
rng(10,27,5) -> [10,15,20,25]
rng(7,null,2) -> [0,2,4,6]
rng(3,-2) -> [3,2,1,0,-1,-2]
rng(3,-2,-2) -> [3,1,-1]
rng(3,-2,2) -> [3,1,-1]
rng(42,42) -> [42]

(Remove the +1 from Array() as is useful/compatible.)

kEnobus
  • 66
  • 5
-1

TypeScript's implementation of Python's range()

const range = (start: number, stop?: number, step: number = 1) => {
  if (stop === undefined) {
    [start, stop] = [0, start];
  }
  return Array.from({ length: Math.ceil((stop - start) / step) }, (_, i) => start + step * i);
};

console.log(range(4)); // [0, 1, 2, 3]
console.log(range(3, 6)); // [3, 4, 5]
console.log(range(0, 10, 2)); // [0, 2, 4, 6, 8]
console.log(range(10, 0, -1)); // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
console.log(range(8, 2, -2)); // [8, 6, 4]
console.log(range(8, 2)); // []
console.log(range(8, 2, 2)); // []
console.log(range(1, 5, -1)); // []
console.log(range(1, 5, -2)); // []
console.log(range(6, 1, -2)); // [6, 4, 2]
console.log(range(1, 6, 2)); // [1, 3, 5]
Tyler Liu
  • 19,552
  • 11
  • 100
  • 84
-2

Recursion function is the best solution for implementing a something like this.

If you want only to get numbers begin from zero

function range(n) {
  if (n > 0){
    return [...range(n-1), n];
   };
   return [0];
};
console.log("range(5) => ", range(5));

For example,

range(5) = [...range(4), 5]
         = [...range(3), 4, 5]
         = [...range(2), 3, 4, 5]
         = [...range(1), 2, 3, 4, 5]
         = [...range(0), 1, 2, 3, 4, 5] // range(0) = [0]
         = [0, 1, 2, 3, 4, 5] //final answer

This function can also extend as following

function range(start, stop, step=1){
  if( stop > start){
    return [...range(start, stop-step), stop];
  }
  return [start];
}
console.log("range(2, 8, 2) => ", range(2, 8, 2));

But note that, unlike in python you have to provide either two or three arguments.

Josef
  • 2,869
  • 2
  • 22
  • 23