Skip to content

Commit 715c88c

Browse files
Iterate over a tree using an ES6 iterator
1 parent eff90b0 commit 715c88c

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

lib/SymbolTree.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ class SymbolTree {
306306
/**
307307
* Iterate over all children of the given object to an array.
308308
*
309-
* `O(1)` (per iterate step)
309+
* `O(1)` for a single iteration
310310
*
311311
* @method childrenIterator
312312
* @memberOf module:symbol-tree#
@@ -343,6 +343,47 @@ class SymbolTree {
343343
return iterator;
344344
}
345345

346+
/**
347+
* Iterate over all descendants of the given object (in tree order).
348+
*
349+
* `O(n)` for the entire iteration<br>
350+
* `O(n)` for a single iteration (worst case)
351+
*
352+
* @method treeIterator
353+
* @memberOf module:symbol-tree#
354+
* @param {Object} root
355+
* @return {Object} An iterable iterator (ES6)
356+
*/
357+
treeIterator(root) {
358+
const following = this.following.bind(this);
359+
360+
let nextObject = root;
361+
const iterator = {};
362+
363+
iterator.next = function() {
364+
if (!nextObject) {
365+
return {
366+
done : true,
367+
value : root
368+
};
369+
}
370+
371+
const value = nextObject;
372+
nextObject = following(nextObject, root);
373+
374+
return {
375+
done : false,
376+
value : value
377+
};
378+
};
379+
380+
iterator[Symbol.iterator] = function() {
381+
return iterator;
382+
};
383+
384+
return iterator;
385+
}
386+
346387
/**
347388
* Remove the object from this tree.
348389
* Has no effect if already removed.

test/SymbolTree.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,3 +782,33 @@ test('treeToArray with filter', function(t) {
782782

783783
t.end();
784784
});
785+
786+
test('tree iterator', function(t) {
787+
const tree = new SymbolTree();
788+
const a = {};
789+
const aa = {};
790+
const ab = {};
791+
const aba = {};
792+
const abaa = {};
793+
const ac = {};
794+
const b = {};
795+
796+
tree.insertLast(aa, a);
797+
tree.insertLast(ab, a);
798+
tree.insertLast(aba, ab);
799+
tree.insertLast(abaa, aba);
800+
tree.insertLast(ac, a);
801+
tree.insertAfter(b, a);
802+
803+
const results = [];
804+
const iterator = tree.treeIterator(a);
805+
806+
for (const object of iterator) {
807+
results.push(object);
808+
}
809+
t.deepEqual([a, aa, ab, aba, abaa, ac], results);
810+
t.deepEqual({done: true, value: a}, iterator.next());
811+
t.deepEqual({done: true, value: a}, iterator.next()); // should keep returning done: true
812+
813+
t.end();
814+
});

0 commit comments

Comments
 (0)