UNPKG

2.82 kBPlain TextView Raw
1// Copyright (c) Jupyter Development Team.
2// Distributed under the terms of the Modified BSD License.
3/*-----------------------------------------------------------------------------
4| Copyright (c) 2014-2017, PhosphorJS Contributors
5|
6| Distributed under the terms of the BSD 3-Clause License.
7|
8| The full license is in the file LICENSE, distributed with this software.
9|----------------------------------------------------------------------------*/
10import { IIterator } from './iter';
11
12/**
13 * An object which can produce a reverse iterator over its values.
14 */
15export interface IRetroable<T> {
16 /**
17 * Get a reverse iterator over the object's values.
18 *
19 * @returns An iterator which yields the object's values in reverse.
20 */
21 retro(): IIterator<T>;
22}
23
24/**
25 * A type alias for a retroable or builtin array-like object.
26 */
27export type RetroableOrArrayLike<T> = IRetroable<T> | ArrayLike<T>;
28
29/**
30 * Create an iterator for a retroable object.
31 *
32 * @param object - The retroable or array-like object of interest.
33 *
34 * @returns An iterator which traverses the object's values in reverse.
35 *
36 * #### Example
37 * ```typescript
38 * import { retro, toArray } from '@lumino/algorithm';
39 *
40 * let data = [1, 2, 3, 4, 5, 6];
41 *
42 * let stream = retro(data);
43 *
44 * toArray(stream); // [6, 5, 4, 3, 2, 1]
45 * ```
46 */
47export function retro<T>(object: RetroableOrArrayLike<T>): IIterator<T> {
48 let it: IIterator<T>;
49 if (typeof (object as any).retro === 'function') {
50 it = (object as IRetroable<T>).retro();
51 } else {
52 it = new RetroArrayIterator<T>(object as ArrayLike<T>);
53 }
54 return it;
55}
56
57/**
58 * An iterator which traverses an array-like object in reverse.
59 *
60 * #### Notes
61 * This iterator can be used for any builtin JS array-like object.
62 */
63export class RetroArrayIterator<T> implements IIterator<T> {
64 /**
65 * Construct a new retro iterator.
66 *
67 * @param source - The array-like object of interest.
68 */
69 constructor(source: ArrayLike<T>) {
70 this._source = source;
71 this._index = source.length - 1;
72 }
73
74 /**
75 * Get an iterator over the object's values.
76 *
77 * @returns An iterator which yields the object's values.
78 */
79 iter(): IIterator<T> {
80 return this;
81 }
82
83 /**
84 * Create an independent clone of the iterator.
85 *
86 * @returns A new independent clone of the iterator.
87 */
88 clone(): IIterator<T> {
89 let result = new RetroArrayIterator<T>(this._source);
90 result._index = this._index;
91 return result;
92 }
93
94 /**
95 * Get the next value from the iterator.
96 *
97 * @returns The next value from the iterator, or `undefined`.
98 */
99 next(): T | undefined {
100 if (this._index < 0 || this._index >= this._source.length) {
101 return undefined;
102 }
103 return this._source[this._index--];
104 }
105
106 private _index: number;
107 private _source: ArrayLike<T>;
108}