Last active
March 28, 2018 19:48
-
-
Save bdurrani/8dac1f03b429a48f3f36085f00b6d1d5 to your computer and use it in GitHub Desktop.
Iterator helper, based on wu.js. Lets you use filter/map/reduce with an iterator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is the iterator, becusae it implements the iterator protocol | |
* Iterator protocol requires an object that implements next() with certain semantics | |
*/ | |
class Chain { | |
constructor(iterable) { | |
this.iterator = Chain.getIterator(iterable); | |
} | |
next() { | |
return this.iterator.next.call(this.iterator); | |
} | |
[Symbol.iterator]() { | |
return this.iterator; | |
} | |
/** | |
* internal filter | |
* @param fn | |
* @returns {IterableIterator<*>} | |
* @private | |
*/ | |
* _filter(fn) { | |
for (let x of this) { | |
if (fn(x)) { | |
yield x; | |
} | |
} | |
} | |
/** | |
* wrapper filter | |
* @param fn | |
* @returns {*} | |
*/ | |
filter(fn = Boolean) { | |
return chain(this._filter(fn)); | |
} | |
* _map(fn) { | |
for (let x of this) { | |
yield fn(x); | |
} | |
}; | |
map(fn) { | |
return chain(this._map(fn)); | |
} | |
reduce(fn, initial) { | |
let val = initial; | |
let first = true; | |
for (let x of this) { | |
if (val === undefined) { | |
val = x; | |
first = false; | |
continue; | |
} | |
val = fn(val, x); | |
} | |
return val; | |
} | |
/** | |
* Return whether a thing is iterable. | |
*/ | |
static isIterable(thing) { | |
return thing && typeof thing[Symbol.iterator] === 'function'; | |
}; | |
/** | |
* Get the iterator for the thing or throw an error. | |
* @param thing | |
* @return {*} | |
*/ | |
static getIterator(thing) { | |
if (Chain.isIterable(thing)) { | |
return thing[Symbol.iterator](); | |
} | |
throw new TypeError('Not iterable: ' + thing); | |
}; | |
} | |
function chain(iterable) { | |
return new Chain(iterable); | |
} | |
for (const item of chain([1, 2, 3, 4]).filter(x => x % 2 === 0).map(x => x + 1)) { | |
console.log(item); | |
} | |
const item2 = chain([1, 2, 3, 4]).filter(x => x % 2 === 0).map(x => x + 1).reduce((x, y) => x + y); | |
console.log(`reduce: ${item2}`); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment