UNPKG

@lumino/algorithm

Version:

Lumino Algorithms and Iterators

135 lines (127 loc) 3.45 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. /*----------------------------------------------------------------------------- | Copyright (c) 2014-2017, PhosphorJS Contributors | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ import { IIterator } from './iter'; /** * Create an iterator of evenly spaced values. * * @param start - The starting value for the range, inclusive. * * @param stop - The stopping value for the range, exclusive. * * @param step - The distance between each value. * * @returns An iterator which produces evenly spaced values. * * #### Notes * In the single argument form of `range(stop)`, `start` defaults to * `0` and `step` defaults to `1`. * * In the two argument form of `range(start, stop)`, `step` defaults * to `1`. */ export function range( start: number, stop?: number, step?: number ): IIterator<number> { if (stop === undefined) { return new RangeIterator(0, start, 1); } if (step === undefined) { return new RangeIterator(start, stop, 1); } return new RangeIterator(start, stop, step); } /** * An iterator which produces a range of evenly spaced values. */ export class RangeIterator implements IIterator<number> { /** * Construct a new range iterator. * * @param start - The starting value for the range, inclusive. * * @param stop - The stopping value for the range, exclusive. * * @param step - The distance between each value. */ constructor(start: number, stop: number, step: number) { this._start = start; this._stop = stop; this._step = step; this._length = Private.rangeLength(start, stop, step); } /** * Get an iterator over the object's values. * * @returns An iterator which yields the object's values. */ iter(): IIterator<number> { return this; } /** * Create an independent clone of the iterator. * * @returns A new independent clone of the iterator. */ clone(): IIterator<number> { let result = new RangeIterator(this._start, this._stop, this._step); result._index = this._index; return result; } /** * Get the next value from the iterator. * * @returns The next value from the iterator, or `undefined`. */ next(): number | undefined { if (this._index >= this._length) { return undefined; } return this._start + this._step * this._index++; } private _index = 0; private _length: number; private _start: number; private _stop: number; private _step: number; } /** * The namespace for the module implementation details. */ namespace Private { /** * Compute the effective length of a range. * * @param start - The starting value for the range, inclusive. * * @param stop - The stopping value for the range, exclusive. * * @param step - The distance between each value. * * @returns The number of steps need to traverse the range. */ export function rangeLength( start: number, stop: number, step: number ): number { if (step === 0) { return Infinity; } if (start > stop && step > 0) { return 0; } if (start < stop && step < 0) { return 0; } return Math.ceil((stop - start) / step); } }