npm i iter-range
const range = require("iter-range");
for (let i of range(10, 0, -1)) {
console.log(i);
}
console.log("Midnight!");
range(4).forEach(() => console.log("#winning"));
This is just a sweet little range library. It implements the same basic API as the python range
function: range([start = 0], stop, [step = 1])
. The key differentiator between this library and the other JavaScript range libraries that I have seen is that it does not create and populate arrays with the given parameters. Instead, I provide you a factory function that builds iterable Range
objects.
Range
objects also include lazily-evaluated implementations of many Array.prototype
methods that match their Array counterparts nearly exactly. If you really want an array, you can always use Array.from(range(2, 12))
or the spread operator [...range(5)]
. There is also a get
method, which will return the value at a given index.
Note that (with the exception of map
, reduce
, reduceRight
, and filter
), these are all constant-space methods. They take advantage of the object's iterable nature and don't create any additional arrays or objects. Furthermore, those that accept a callback are written to break early if possible; a some
call that matches on the first item stops there and returns. Likewise, indexOf
, lastIndexOf
, includes
, and get
are all constant-time operations.
This library exports a single function range
, which is a factory for producing Range
objects. Range
objects are iterable and have a length:
const range = require("iter-range");
for (let i of range(5)) {
console.log(i); // logs 0, then 1, then 2, etc.
}
// Decreasing and non-integer parameters work a treat:
console.log(...range(27, 8, -4.5)); //=> 27 22.5 18 13.5 9
// The iterator resets when consumed:
const r = range(3);
console.log(...r); //=> 0 1 2
console.log(Array.from(r)); //=> [0, 1, 2]
console.log(...r); //=> 0 1 2
// They have a length property
console.log(range(5).length); //=> 5
console.log(range(0, 10, 3).length); //=> 4
Additionally, Range
objects have a whole posse of the standard Array.prototype
methods (and get
):
const range = require("iter-range");
console.log(range(3, 6).map((i, index) => [i, index])); //=> [[3, 0], [4, 1], [5, 2]]
console.log(...range(5).reverse()); //=> 4 3 2 1 0
console.log(range(8).filter(i => i % 2 === 0)); //=> [0, 2, 4, 6]
console.log(range(2.5, -2.75, -0.25).includes(1)); //=> true
console.log(range(10, 0, -1).indexOf(3)); //=> 7
console.log(range(2.5, 15, 1.25).get(2)); //=> 5
I have strived to match the Array API precisely for these methods. For details, refer to the Range
API documentation below.
-
Since these methods don't construct an array to iterate over, there is no array to pass to the callbacks that would normally receive them. Instead they pass the
Range
object as the third parameter. I hope that's helpful. -
Reverse does not mutate the
Range
it is called on, it just returns a new instance.
The Range
object methods are thoroughly tested to match their Array.prototype
counterparts (except as noted). Please let me know if I've missed or wrongly implemented anything. Jasmine is used for tests, Istanbul is used to ensure complete test coverage, ESLint is used for linting, and jsdoc-to-markdown is used to generate the documentation. You can prepare the dev environment by cloning the repository and installing the dependencies ($ npm i
).
- Tests:
npm test
- Coverage:
npm coverage
- Linting:
npm run lint
- Documentation:
npm run doc
{{#function name="range"}} {{>docs}} {{/function}}
{{#class name="Range"}} {{>docs}} {{/class}}
{{#identifier name="iterCallback"}} {{>docs}} {{/identifier}}
{{#identifier name="reduceCallback"}} {{>docs}} {{/identifier}}