iteragain
Version:
Javascript Iterable/Iterator/Generator-function utilities.
79 lines • 2.88 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RangeIterator = void 0;
const toArray_1 = require("../toArray");
/**
* A class for representing a range of numbers and also iterating through them. When `next.done` is true, resets the
* internal counter back to `start`.
*/
class RangeIterator {
constructor(...params) {
/** Alias of `includes`. */
this.has = this.includes;
/** Alias of `nth`. */
this.at = this.nth;
let start = 0, stop = 0;
let step;
if (params.length === 1)
stop = params[0];
else if (params.length > 1)
[start, stop, step] = params;
if (typeof step !== 'number')
step = Math.sign(stop - start);
const stepSign = Math.sign(step);
if (stepSign === 0)
this.next = () => ({ done: true, value: undefined });
this.start = this.i = start;
this.stop = stop;
this.step = step;
this.stepSign = stepSign;
// If the start is not in this range, then it's 0, otherwise calc normally.
this._length = this.includes(start) ? Math.abs(Math.ceil((stop - start) / step)) : 0;
}
/** The length of this range of numbers. */
get length() {
return this._length;
}
[Symbol.iterator]() {
return this;
}
next() {
if (Math.sign(this.stop - this.i) !== this.stepSign) {
this.i = this.start;
return { done: true, value: undefined };
}
const value = this.i;
this.i += this.step;
return { done: false, value };
}
/** Returns true if `n` is inside of this range. */
includes(n) {
if ((n - this.start) % this.step !== 0)
return false;
return this.stepSign > 0 ? n >= this.start && n < this.stop : n <= this.start && n > this.stop;
}
/** Returns the number at `index` in this range. `index` can be negative to access indices starting from the end. */
nth(index) {
const num = index >= 0 ? this.start + index * this.step : this.stop + index * this.step;
return this.includes(num) ? num : undefined;
}
/** Returns the index that `n` is at in this range. */
index(n) {
return (n - this.start) / this.step;
}
/** Returns true if this range is equal to another. */
equal(other) {
return this.start === other.start && this.stop === other.stop && this.step === other.step;
}
// slice(start: number, end?: number) {}
toString() {
return `range(${this.start}, ${this.stop}, ${this.step})`;
}
/** Iterates and collects all values into an Array. */
toArray() {
return (0, toArray_1.default)(this);
}
}
exports.RangeIterator = RangeIterator;
exports.default = RangeIterator;
//# sourceMappingURL=RangeIterator.js.map