Is there any ECMAScript 6/7 equivalent to underscore’s range
function?
In underscore:
_.range(startPage, endPage + 1);
In ES2015:
Array.from(Array(n), (_, i) => x + i)
Not sure how the ES2015 version works. I would like to know how range in ecmascript of javascript works
The idea is to create an array of length end - start + 1
, and then fill it with the relevant numbers using Array#from.
The Array.from() method creates a new Array instance from an array-like or iterable object.
In this case Array#from needs an object with the length property. Using Array(n)
creates such an object (array). You can also use { length: n }
directly. In this case n = Math.abs(end - start) + 1
.
Array#from accepts a mapFn
callback, a function that can transform the iterated value. The function receives 2 params - the values (which we can ignore in this case), and the index (0 based). Adding start
to the current index will create the numbers in the range.
const range = (start, end) => Array.from(
Array(Math.abs(end - start) + 1),
(_, i) => start + i
);
console.log(range(5, 10));
console.log(range(-10, -5));
console.log(range(-5, 10));
This version will handle reverse range as well (large to small) as well:
const range = (start, end) => {
const inc = (end - start) / Math.abs(end - start);
return Array.from(
Array(Math.abs(end - start) + 1),
(_, i) => start + i * inc
);
};
console.log(range(5, 10));
console.log(range(-5, -10));
console.log(range(10, -5));
Note that the following implementation does not allow for lazy-generated lists:
Array.from(Array(n), (_, i) => x + i)
Imagine that you need a list of 1M numbers:
range(1, 1000000);
Are you going to consume all of them? Maybe not, yet all the numbers have been generated already and they probably left a non-trivial footprint on your memory.
It would be nice if we could get them one by one on demand.
It turns out we can do exactly that with a generator:
function* range(start, end, step = 1) {
for (let value = start; value < end; value += step) {
yield value;
}
}
for (let x of range(1, Infinity)) {
if (x > 10) {
break;
}
console.log(x);
}
Did you notice the range(1, Infinity)
bit?
In a classic implementation where all the numbers are generated in advance, this code wouldn't even run as you would get stuck in an infinite number-generating loop.
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