lazyds v0.1.0
Lazy Data Structures
This is a data structures library written in JavaScript. It exposes a number of standard data structures as well as a lazily evaluated LINQ-like API. Docs at http://cristiandima.github.io/lazyds/. Source at http://github.com/cristiandima/lazyds/.
Test coverage is high, almost 100%, for the more complicated data structures and linq-like methods, but non existent for the more basic objects (e.g. the stack which is nothing but a wrapper around the array push/pop methods - hopefully no mistakes there).
Node install
npm install lazyds
Data structures available:
- Stack (Enumerable)
- Queue (Enumerable)
- List (Enumerable)
- Sorted List (Enumerable)
- Linked List (Iterable)
- HashSet (Iterable)
- Binary Heap (Iterable)
- Priority Queue (Iterable)
Usage:
// load everything
var ds = require('lazyds');
// usage
var l = new ds.List();
var s = new ds.Stack();
// load only the queue object
var Queue = require('lazyds/lib/queue.js').Queue;
// usage
var q = new Queue();
Testing:
// mocha testing
npm run test
// istanbul test coverage
npm run coverage
Extension methods available:
take, takeWhile, skip, skipLast, skipWhile, count,
empty, contains, first, last, firstIndexOf, lastIndexOf,
where, select, forEach, all, any, groupBy, aggregate,
max, min, sum, toArray, toHashSet, range, repeat
All data structures expose the methods you'd normally expect them to. Beyond that they expose the LINQ-like API by inheriting either the Iterable or Enumerable object. The inheritance chain goes Iterable > Enumerable > DataStructure. The closer the method definition is to the data structure the more efficient it is. Enumerables are objects using an array as a backing data store. Iterables are objects that expose their backing collection via an iterator. The use of iterators allows for lazy evaluation and infinite data structures.
Code examples:
var q = new PriorityQueue();
q.enqueue(5, "A");
q.enqueue(4, "B");
q.enqueue(3, "C");
q.enqueue(2, "D");
// prints "C" and "D"
q.where(function(elm){
return elm.priority < 4;
}).select(function(elm){
return elm.value;
}).forEach(function(letter){
console.log(letter);
});
// prints D, C, B, A
while(!q.empty()){
console.log(q.dequeue().value);
}
var list = new List([1, 4, 3, 2, 4, 6, 8, 9]);
var isEven = function(elm){
return elm % 2 === 0;
}
var square = function(n){
return n*n;
}
// print 16, 4, 16
list.where(isEven).take(3).select(square).forEach(console.log);
// print 4, 3, 2, 4
list.skip(1).takeWhile(function(n){return n<6;}).forEach(console.log);
var sorted = new SortedList();
sorted.addRange([9, 3, 5]);
sorted.forEach(console.log); // logs 3, 5, 9
sorted.addRange(Enumerable.range(5).where(isEven));
console.log(sorted.toArray()); // logs [0, 2, 3, 4, 5, 9]
// inifinte range
var range = Iterable.range().where(isEven).select(square);
// evaluation only happens on the toArray() call
console.log(range.take(5).toArray()); // logs [0, 4, 16, 36, 64]