Skip to content

Commit 051ef85

Browse files
committed
use generator fn instead of an iterator class
1 parent 6383b25 commit 051ef85

File tree

6 files changed

+94
-119
lines changed

6 files changed

+94
-119
lines changed

README.md

+15-9
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,27 @@ Clear tree
171171
tree.clear()
172172
```
173173

174-
### Iterator([interval, outputMapperFn])
175-
Returns a stateful iterator. <br/>
174+
### Iterate([interval, outputMapperFn])
175+
Returns an iterator (and iterable). <br/>
176176
Call `next` on the iterator to navigate to successor tree nodes and return the corresponding values. <br/>
177-
In the absence of a starting interval, the iterator will start with a `null` state. <br/>
178-
If there is no successor node when `next` is called, the iterator will have a `null` state and return `null`. <br/>
179-
If the iterator has a `null` state, calling `next` will take the iterator to the minimum node in the tree.
177+
In the absence of a starting interval, the iterator will start with the lowest interval. <br/>
180178
```javascript
181-
let iterator = tree.iterator();
182-
let next = iterator.next();
179+
let iterator = tree.iterate();
180+
let next = iterator.next().value;
183181
```
184182
Optional *outputMapperFn(value, key)* enables to map search results into custom defined output. <br/>
185183
Example:
186184
```javascript
187-
let iterator = tree.iterator([5,5], (value, key) => key);
188-
let next_key = iterator.next();
185+
let iterator = tree.iterate([5,5], (value, key) => key);
186+
let next_key = iterator.next().value;
187+
```
188+
Supports `for .. of` syntax. <br/>
189+
Example:
190+
```javascript
191+
for (let key of tree.iterate([5,5], (value, key) => key)) {
192+
if (key[0] > 8) break;
193+
console.log(key);
194+
}
189195
```
190196

191197
## Documentation

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"types": "index.d.ts",
1212
"nyc": {
1313
"require": [
14-
"@babel/register"
14+
"@babel/register",
15+
"@babel/polyfill"
1516
],
1617
"sourceMap": false,
1718
"instrument": false

src/classes/intervalTree.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
*/
44
'use strict';
55

6-
import Iterator from './iterator.js';
76
import Node from './node.js';
87
import {RB_TREE_COLOR_RED, RB_TREE_COLOR_BLACK} from '../utils/constants.js';
98

@@ -169,12 +168,21 @@ class IntervalTree {
169168
}
170169

171170
/**
172-
* @param {Interval} interval - may be null if the iterator is intended to start from the beginning or end
171+
* @param {Interval} interval - optional if the iterator is intended to start from the beginning or end
173172
* @param outputMapperFn(value,key) - optional function that maps (value, key) to custom output
174173
* @returns {Iterator}
175174
*/
176-
iterator(interval, outputMapperFn = (value, key) => value === key ? key.output() : value) {
177-
return new Iterator(this, interval, outputMapperFn);
175+
*iterate(interval, outputMapperFn = (value, key) => value === key ? key.output() : value) {
176+
let node;
177+
if (interval) {
178+
node = this.tree_search_nearest_forward(this.root, new Node(interval));
179+
} else if (this.root) {
180+
node = this.local_minimum(this.root);
181+
}
182+
while (node) {
183+
yield outputMapperFn(node.item.value, node.item.key);
184+
node = this.tree_successor(node);
185+
}
178186
}
179187

180188
recalc_max(node) {

src/classes/iterator.js

-49
This file was deleted.

test/intervalTree.js

+65
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,69 @@ describe('#IntervalTree', function() {
310310
const resp2 = tree.search([4,11]);
311311
expect(resp2).to.deep.equal([[5,7],[7,8]]);
312312
})
313+
describe('##Iterator', function() {
314+
it('May find first intersecting interval', function () {
315+
let tree = new IntervalTree();
316+
let ints = [[6,8],[1,3],[5,12],[1,1],[5,7]];
317+
for (let int of ints) tree.insert(int);
318+
let iterator = tree.iterate([3,8]);
319+
expect(iterator.next().value).to.deep.equal([1,3]);
320+
});
321+
it('May find first forward interval when there is no intersection', function () {
322+
let tree = new IntervalTree();
323+
let ints = [[6,8],[1,3],[5,12],[1,1],[5,7]];
324+
for (let int of ints) tree.insert(int);
325+
let iterator = tree.iterate([4,4]);
326+
expect(iterator.next().value).to.deep.equal([5,7]);
327+
});
328+
it('May find first interval when no interval is passed', function () {
329+
let tree = new IntervalTree();
330+
let ints = [[6,8],[1,3],[5,12],[1,1],[5,7]];
331+
for (let int of ints) tree.insert(int);
332+
let iterator = tree.iterate();
333+
expect(iterator.next().value).to.deep.equal([1,1]);
334+
});
335+
it('Supports iteration with `for .. of` syntax', function () {
336+
let tree = new IntervalTree();
337+
let ints = [[6,8],[1,3],[5,12],[1,1],[5,7]];
338+
for (let int of ints) tree.insert(int);
339+
let results = [];
340+
for (let val of tree.iterate([4,4])) {
341+
results.push(val);
342+
}
343+
expect(results).to.deep.equal([[5,7],[5,12],[6,8]]);
344+
});
345+
it('Returns `{done: true}` when it reaches the end', function () {
346+
let tree = new IntervalTree();
347+
let ints = [[6,8],[1,3],[5,12],[1,1],[5,7]];
348+
for (let int of ints) tree.insert(int);
349+
let iterator = tree.iterate([8,8]);
350+
expect(iterator.next().value).to.deep.equal([5,12]);
351+
expect(iterator.next().value).to.deep.equal([6,8]);
352+
let res = iterator.next();
353+
expect(res.value).to.equal(undefined);
354+
expect(res.done).to.equal(true);
355+
});
356+
it('Supports custom transformed objects', function () {
357+
const composers = [
358+
{name: "Ludwig van Beethoven", period: [1770,1827]},
359+
{name: "Johann Sebastian Bach", period: [1685, 1750]},
360+
{name: "Wolfgang Amadeus Mozart", period: [1756, 1791]},
361+
{name: "Johannes Brahms", period: [1833, 1897]},
362+
{name: "Richard Wagner", period: [1813, 1883]},
363+
{name: "Claude Debussy", period: [1862, 1918]},
364+
{name: "Pyotr Ilyich Tchaikovsky", period: [1840, 1893]},
365+
{name: "Frédéric Chopin", period: [1810, 1849]},
366+
{name: "Joseph Haydn", period: [1732, 1809]},
367+
{name: "Antonio Vivaldi", period: [1678, 1741]}
368+
];
369+
const tree = new IntervalTree();
370+
for (let composer of composers)
371+
tree.insert(composer.period, composer.name);
372+
let iterator = tree.iterate([1600, 1700],
373+
(name, period) => {return `${name} (${period.low}-${period.high})`});
374+
expect(iterator.next().value).to.equal("Antonio Vivaldi (1678-1741)");
375+
expect(iterator.next().value).to.equal("Johann Sebastian Bach (1685-1750)");
376+
});
377+
});
313378
});

test/iterator.js

-56
This file was deleted.

0 commit comments

Comments
 (0)