In PHP, you can do...
range(1, 3); // Array(1, 2, 3)
range("A", "C"); // Array("A", "B", "C")
That is, there is a function that lets you get a range of numbers or characters by passing the upper and lower bounds.
Is there anything built-in to JavaScript natively for this? If not, how would I implement it?
Numbers
[...Array(5).keys()];
=> [0, 1, 2, 3, 4]
Character iteration
String.fromCharCode(...[...Array('D'.charCodeAt(0) - 'A'.charCodeAt(0) + 1).keys()].map(i => i + 'A'.charCodeAt(0)));
=> "ABCD"
Iteration
for (const x of Array(5).keys()) {
console.log(x, String.fromCharCode('A'.charCodeAt(0) + x));
}
=> 0,"A" 1,"B" 2,"C" 3,"D" 4,"E"
As functions
function range(size, startAt = 0) {
return [...Array(size).keys()].map(i => i + startAt);
}
function characterRange(startChar, endChar) {
return String.fromCharCode(...range(endChar.charCodeAt(0) -
startChar.charCodeAt(0), startChar.charCodeAt(0)))
}
As typed functions
function range(size:number, startAt:number = 0):ReadonlyArray<number> {
return [...Array(size).keys()].map(i => i + startAt);
}
function characterRange(startChar:string, endChar:string):ReadonlyArray<string> {
return String.fromCharCode(...range(endChar.charCodeAt(0) -
startChar.charCodeAt(0), startChar.charCodeAt(0)))
}
lodash.js _.range()
function
_.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]
String.fromCharCode(..._.range('A'.charCodeAt(0), 'D'.charCodeAt(0) + 1));
=> "ABCD"
Old non es6 browsers without a library:
Array.apply(null, Array(5)).map(function (_, i) {return i;});
=> [0, 1, 2, 3, 4]
console.log([...Array(5).keys()]);
(ES6 credit to nils petersohn and other commenters)
For numbers you can use ES6 Array.from()
, which works in everything these days except IE:
Shorter version:
Array.from({length: 20}, (x, i) => i);
Longer version:
Array.from(new Array(20), (x, i) => i);
which creates an array from 0 to 19 inclusive. This can be further shortened to one of these forms:
Array.from(Array(20).keys());
// or
[...Array(20).keys()];
Lower and upper bounds can be specified too, for example:
Array.from(new Array(20), (x, i) => i + *lowerBound*);
An article describing this in more detail: http://www.2ality.com/2014/05/es6-array-methods.html
My new favorite form (ES2015)
Array(10).fill(1).map((x, y) => x + y)
And if you need a function with a step
param:
const range = (start, stop, step = 1) =>
Array(Math.ceil((stop - start) / step)).fill(start).map((x, y) => x + y * step)
Another possible implementation suggested by the MDN docs:
// 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))
Here's my 2 cents:
function range(start, end) {
return Array.apply(0, Array(end - 1))
.map((element, index) => index + start);
}
It works for characters and numbers, going forwards or backwards with an optional step.
var range = function(start, end, step) {
var range = [];
var typeofStart = typeof start;
var typeofEnd = typeof end;
if (step === 0) {
throw TypeError("Step cannot be zero.");
}
if (typeofStart == "undefined" || typeofEnd == "undefined") {
throw TypeError("Must pass start and end arguments.");
} else if (typeofStart != typeofEnd) {
throw TypeError("Start and end arguments must be of same type.");
}
typeof step == "undefined" && (step = 1);
if (end < start) {
step = -step;
}
if (typeofStart == "number") {
while (step > 0 ? end >= start : end <= start) {
range.push(start);
start += step;
}
} else if (typeofStart == "string") {
if (start.length != 1 || end.length != 1) {
throw TypeError("Only strings with one character are supported.");
}
start = start.charCodeAt(0);
end = end.charCodeAt(0);
while (step > 0 ? end >= start : end <= start) {
range.push(String.fromCharCode(start));
start += step;
}
} else {
throw TypeError("Only string and number types are supported");
}
return range;
}
jsFiddle.
If augmenting native types is your thing, then assign it to Array.range
.
var range = function(start, end, step) {
var range = [];
var typeofStart = typeof start;
var typeofEnd = typeof end;
if (step === 0) {
throw TypeError("Step cannot be zero.");
}
if (typeofStart == "undefined" || typeofEnd == "undefined") {
throw TypeError("Must pass start and end arguments.");
} else if (typeofStart != typeofEnd) {
throw TypeError("Start and end arguments must be of same type.");
}
typeof step == "undefined" && (step = 1);
if (end < start) {
step = -step;
}
if (typeofStart == "number") {
while (step > 0 ? end >= start : end <= start) {
range.push(start);
start += step;
}
} else if (typeofStart == "string") {
if (start.length != 1 || end.length != 1) {
throw TypeError("Only strings with one character are supported.");
}
start = start.charCodeAt(0);
end = end.charCodeAt(0);
while (step > 0 ? end >= start : end <= start) {
range.push(String.fromCharCode(start));
start += step;
}
} else {
throw TypeError("Only string and number types are supported");
}
return range;
}
console.log(range("A", "Z", 1));
console.log(range("Z", "A", 1));
console.log(range("A", "Z", 3));
console.log(range(0, 25, 1));
console.log(range(0, 25, 5));
console.log(range(20, 5, 5));
Simple range function:
function range(start, stop, step) {
var a = [start], b = start;
while (b < stop) {
a.push(b += step || 1);
}
return a;
}
To incorporate the BigInt data type some check can be included, ensuring that all variables are same typeof start
:
function range(start, stop, step) {
var a = [start], b = start;
if (typeof start == 'bigint') {
stop = BigInt(stop)
step = step? BigInt(step): 1n;
} else
step = step || 1;
while (b < stop) {
a.push(b += step);
}
return a;
}
To remove values higher than defined by stop
e.g. range(0,5,2)
will include 6
, which shouldn't be.
function range(start, stop, step) {
var a = [start], b = start;
while (b < stop) {
a.push(b += step || 1);
}
return (b > stop) ? a.slice(0,-1) : a;
}
OK, in JavaScript we don't have a range()
function like PHP, so we need to create the function which is quite easy thing, I write couple of one-line functions for you and separate them for Numbers and Alphabets as below:
for Numbers:
function numberRange (start, end) {
return new Array(end - start).fill().map((d, i) => i + start);
}
and call it like:
numberRange(5, 10); //[5, 6, 7, 8, 9]
for Alphabets:
function alphabetRange (start, end) {
return new Array(end.charCodeAt(0) - start.charCodeAt(0)).fill().map((d, i) => String.fromCharCode(i + start.charCodeAt(0)));
}
and call it like:
alphabetRange('c', 'h'); //["c", "d", "e", "f", "g"]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With