JavaScript function similar to Python range()
JavascriptPythonJavascript Problem Overview
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;
}
Javascript Solutions
Solution 1 - Javascript
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()]
Solution 2 - Javascript
No, there is none, but you can make one.
range()
JavaScript's implementation of Python's 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.
range()
in JavaScript and Python
Comparison between 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.
Solution 3 - Javascript
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
Solution 4 - Javascript
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
Solution 5 - Javascript
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);
=> []
Solution 6 - Javascript
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
Solution 7 - Javascript
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);
Solution 8 - Javascript
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]
Solution 9 - Javascript
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
Solution 10 - Javascript
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
}
Solution 11 - Javascript
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.
Solution 12 - Javascript
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]
Solution 13 - Javascript
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"]
Solution 14 - Javascript
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));
Solution 15 - Javascript
You may use underscore library. It contains dozens of useful functions for working with arrays and many more.
Solution 16 - Javascript
> 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]
Solution 17 - Javascript
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.
Solution 18 - Javascript
> 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()):
range(stop)
range(start, stop)
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...
}
Solution 19 - Javascript
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)
}
Solution 20 - Javascript
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 ;)
Solution 21 - Javascript
function range(start, stop) {
if (typeof stop == 'undefined') {
stop = start;
start = 0;
}
result = [...Array(stop).keys()].slice(start, stop);
return result;
}
Solution 22 - Javascript
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}`)
}
Solution 23 - Javascript
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.
Solution 24 - Javascript
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)];
}
refer to here for more.
Solution 25 - Javascript
Here's how i do it
let n = 5
[...Array(n).keys()].map(x=>{console.log(x)})
output
0
1
2
3
4
Solution 26 - Javascript
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.
Solution 27 - Javascript
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]