diff --git a/src/table/table.js b/src/table/table.js index b05c8532..8d4b94f1 100644 --- a/src/table/table.js +++ b/src/table/table.js @@ -440,7 +440,7 @@ export default class Table extends Transformable { } } else if (filter) { let c = n - i + 1; - for (i = filter.nth(i); --c; i = filter.next(i + 1)) { + for (i = filter.nth(i); --c && i > -1; i = filter.next(i + 1)) { fn(i, data, stop); } } else { diff --git a/test/table/column-table-test.js b/test/table/column-table-test.js index 48f0170b..d10cf0ea 100644 --- a/test/table/column-table-test.js +++ b/test/table/column-table-test.js @@ -104,6 +104,33 @@ tape('ColumnTable scan supports filtering and ordering', t => { t.end(); }); +tape('ColumnTable scan supports early termination', t => { + const table = new ColumnTable({ + a: ['a', 'a', 'a', 'b', 'b'], + b: [2, 1, 4, 5, 3] + }); + + let count; + const visitor = (row, data, stop) => { if (++count > 1) stop(); }; + + count = 0; + table.scan(visitor, true); + t.equal(count, 2, 'standard scan'); + + count = 0; + const filter = new BitSet(5); + [1, 2, 4].forEach(i => filter.set(i)); + table.create({ filter }).scan(visitor, true); + t.equal(count, 2, 'filtered scan'); + + count = 0; + const order = (u, v, { b }) => b.get(u) - b.get(v); + table.create({ order }).scan(visitor, true); + t.equal(count, 2, 'ordered scan'); + + t.end(); +}); + tape('ColumnTable memoizes indices', t => { const ut = new ColumnTable({ v: [1, 3, 2] }); const ui = ut.indices(false);