From 17acfffd47bc8ab4bccdf075e91a6b48b3b34103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Ooms?= Date: Thu, 25 Mar 2021 17:17:41 +0100 Subject: [PATCH] :sparkles: feat: Add method `reversed()`. Fixes #107. --- README.md | 11 +++++++++- src/1-digit/0-Digit.js | 4 ++++ src/2-node/2-Node2.js | 4 ++++ src/2-node/3-Node3.js | 4 ++++ src/3-tree/implementations/0-Empty.js | 2 ++ src/3-tree/implementations/1-Single.js | 8 +++++--- src/3-tree/implementations/2-Deep.js | 6 ++++++ src/4-lazy/0-Lazy.js | 4 ++++ test/src/methods/reversed.js | 28 ++++++++++++++++++++++++++ 9 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 test/src/methods/reversed.js diff --git a/README.md b/README.md index 638b309d..2641645a 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,8 @@ Parent is [@aureooms/js-persistent](https://github.com/aureooms/js-persistent). * [`Tree#takeUntil(Function) -> Tree`](#treetakeuntilfunction---tree) * [`Tree#dropUntil(Function) -> Tree`](#treedropuntilfunction---tree) * [:flying_saucer: Visit](#flying_saucer-visit) - * [`TreeSymbol.iterator -> Iterable`](#treesymboliterator---iterable) + * [`Tree[Symbol.iterator]() -> Iterable`](#treesymboliterator---iterable) + * [`Tree#reversed() -> Iterable`](#treereversed---iterable) * [:scroll: References](#scroll-references) * [:link: Links](#link-links) @@ -306,6 +307,14 @@ Returns an iterator on the values of the tree in left-to-right order. for ( const x of tree ) console.log( x ) ; ``` +#### `Tree#reversed() -> Iterable` + +Returns an iterator on the values of the tree in right-to-left order. + +```js +for ( const x of tree.reversed() ) console.log( x ) ; +``` + ## :scroll: References diff --git a/src/1-digit/0-Digit.js b/src/1-digit/0-Digit.js index c2752d3e..1be2134c 100644 --- a/src/1-digit/0-Digit.js +++ b/src/1-digit/0-Digit.js @@ -13,3 +13,7 @@ Digit.prototype._nodes_with_list = function (M, list, other) { Digit.prototype[Symbol.iterator] = function () { return this._list()[Symbol.iterator](); }; + +Digit.prototype.reversed = function () { + return this._list().reverse()[Symbol.iterator](); +}; diff --git a/src/2-node/2-Node2.js b/src/2-node/2-Node2.js index 40f04389..c6415a3f 100644 --- a/src/2-node/2-Node2.js +++ b/src/2-node/2-Node2.js @@ -10,6 +10,10 @@ Node2.prototype[Symbol.iterator] = function () { return [this.a, this.b][Symbol.iterator](); }; +Node2.prototype.reversed = function () { + return [this.b, this.a][Symbol.iterator](); +}; + Node2.prototype.measure = function () { return this.v; }; diff --git a/src/2-node/3-Node3.js b/src/2-node/3-Node3.js index 89d9313c..940f52b8 100644 --- a/src/2-node/3-Node3.js +++ b/src/2-node/3-Node3.js @@ -11,6 +11,10 @@ Node3.prototype[Symbol.iterator] = function () { return [this.a, this.b, this.c][Symbol.iterator](); }; +Node3.prototype.reversed = function () { + return [this.c, this.b, this.a][Symbol.iterator](); +}; + Node3.prototype.measure = function () { return this.v; }; diff --git a/src/3-tree/implementations/0-Empty.js b/src/3-tree/implementations/0-Empty.js index d8a9dcfc..fd8af226 100644 --- a/src/3-tree/implementations/0-Empty.js +++ b/src/3-tree/implementations/0-Empty.js @@ -49,6 +49,8 @@ Empty.prototype[Symbol.iterator] = function () { return _EMPTY; }; +Empty.prototype.reversed = function* () {}; + /** * It is assumed that p(i+|this|) is true. */ diff --git a/src/3-tree/implementations/1-Single.js b/src/3-tree/implementations/1-Single.js index 96e34296..46412581 100644 --- a/src/3-tree/implementations/1-Single.js +++ b/src/3-tree/implementations/1-Single.js @@ -57,9 +57,11 @@ Single.prototype.concat = function (other) { return other.cons(this.a); }; -Single.prototype[Symbol.iterator] = function* () { - yield this.a; -}; +Single.prototype[Symbol.iterator] = + // eslint-disable-next-line no-multi-assign + Single.prototype.reversed = function* () { + yield this.a; + }; /** * It is assumed that p(i+|this|) is true. diff --git a/src/3-tree/implementations/2-Deep.js b/src/3-tree/implementations/2-Deep.js index b6ec1221..19e0b120 100644 --- a/src/3-tree/implementations/2-Deep.js +++ b/src/3-tree/implementations/2-Deep.js @@ -120,6 +120,12 @@ Deep.prototype[Symbol.iterator] = function* () { yield* this.right; }; +Deep.prototype.reversed = function* () { + yield* this.right.reversed(); + for (const node of this.middle.reversed()) yield* node.reversed(); + yield* this.left.reversed(); +}; + /** * It is assumed that p(i+|this|) is true. */ diff --git a/src/4-lazy/0-Lazy.js b/src/4-lazy/0-Lazy.js index d7bd80bc..797194cc 100644 --- a/src/4-lazy/0-Lazy.js +++ b/src/4-lazy/0-Lazy.js @@ -63,3 +63,7 @@ Lazy.prototype.concat = function (other) { Lazy.prototype[Symbol.iterator] = function () { return this.force()[Symbol.iterator](); }; + +Lazy.prototype.reversed = function () { + return this.force().reversed(); +}; diff --git a/test/src/methods/reversed.js b/test/src/methods/reversed.js new file mode 100644 index 00000000..d008f750 --- /dev/null +++ b/test/src/methods/reversed.js @@ -0,0 +1,28 @@ +import test from 'ava'; + +import {Measures} from '@aureooms/js-measure'; +const {COUNTER} = Measures; + +import {list, range, tee, reversed} from '@aureooms/js-itertools'; + +import {from} from '../../../src/index.js'; + +const macro = (t, iterable) => { + const [copy1, copy2] = tee(iterable, 2); + const expected = list(reversed(copy1)); + const actual = list(from(COUNTER, copy2).reversed()); + t.deepEqual(actual, expected); +}; + +macro.title = (title, iterable) => + `from(COUNTER, ${title || JSON.stringify(iterable)})`; + +test(macro, []); +test('range(0)', macro, range(0)); +test(macro, [0]); +test(macro, 'ab'); +test(macro, '724'); +test(macro, 'abcd'); +test('range(9)', macro, range(9)); +test('range(1000)', macro, range(1000)); +test('range(100000)', macro, range(100000));