genii
v0.1.1
Published
``` npm install genii ```
Downloads
3
Maintainers
Readme
npm install genii
There is just one function:
import { range } from "genii";
Iterator Utilities
The range
function creates a lazy generator sequence:
import { range } from "genii";
for(let i of range(5)) {
console.log(i)
}
// 0, 1, 2, 3, 4
The range
iterator is augumented with some useful methods:
let numbers =
range(100)
.filter(i => i % 2 == 0)
.map(i => i * 10)
.offset(20)
.limit(5);
for(let i of numbers) {
console.log(i)
}
// 400
// 420
// 440
// 460
// 480
Use the array
method to collect the iteration result into an array:
range(100)
.filter(i => i % 2 == 0)
.map(i => i * 10)
.offset(20)
.limit(5)
.array();
// [ 400, 420, 440, 460, 480 ]
Iterating through an array with range
:
for(let value of range([1,2,3]).map(i => i * 10)) {
console.log(value);
}
// 10
// 20
// 30
Iterating through an object with range
:
for(let value of range({a: 1, b: 2, c: 3}).map(i => i * 10)) {
console.log(value);
}
// 10
// 20
// 30
Creating Dictionaries
The dict
method makes it easy to create dictionaries. To convert an array to a dictionary (using the array index as key):
range([0,1,2]).dict()
// { '0': 0, '1': 1, '2': 2 }
We can achieve the same result with a number range:
range(3).dict()
// { '0': 0, '1': 1, '2': 2 }
Instead of using the position as key, we can use the reindex
method to change the keys:
range(3).reindex(val => `key-${val}`).dict()
{ 'key-0': 0, 'key-1': 1, 'key-2': 2 }
We also reindex an object:
range({a: 1, b: 2, c: 3}).reindex(val => `key-${val}`).dict()
// { 'key-1': 1, 'key-2': 2, 'key-3': 3 }
Indexed Iteration
Under the hood, the genii iterator aguments the ES6 iteration protocol with the index
property:
interface Next<K, V> {
done: boolean;
value?: V;
index?: K;
}
By doing this, we can treat objects and arrays as interchangeable.
- Both objects and arrays can be iterated as sequence.
- We can always convert a sequence to object, using
index
as the key. - We can always convert a sequence to an array, collecting
value
.
API
export function range<T>(dict: { [key: string]: T }): IndexGenerator<string, T>;
export function range<T>(arg: T[]): IndexGenerator<number, T>;
export function range(rangeEnd: number): IndexGenerator<number, number>;
export function range(rangeStart: number, rangeEnd: number): IndexGenerator<number, number>;
export function range(rangeStart: number, rangeEnd: number, step: number): IndexGenerator<number, number>;
interface IndexGenerator<K, V> {
// Next item.
next(): Next<K, V>;
// Filter the sequence.
filter(fn: FilterFunction<K, V>): IndexGenerator<K, V>;
// Transform the sequence.
map<Result>(fn: MapFunction<K, V, Result>): IndexGenerator<K, Result>;
// Transform the index of the sequence.
reindex<Result>(fn: IndexFunction<K, V, Result>): IndexGenerator<Result, V>;
// Restrict the length of the sequence.
limit(size: number): IndexGenerator<K, V>;
// Shift the sequence.
offset(offset: number): IndexGenerator<K, V>;
// Allow side-effect while iterating through the sequence.
tap(f: TapFunction<K, V>): IndexGenerator<K, V>;
// collect sequence values into array
array(): V[];
// collect sequence key/values into dictionary
dict(): { [key: string]: V }
[Symbol.iterator]: () => {
next: NextFunction<K, V>;
};
}
interface Next<K, V> {
done: boolean;
value?: V;
index?: K;
}
type FilterFunction<K, V> = (value: V, key: K) => boolean;
type MapFunction<K, V, Result> = (value: V, key: K) => Result;
type TapFunction<K, V> = (value: V, key: K) => any;
type IndexFunction<K, V, Result> = (value: V, index: K) => Result;
type NextFunction<K, V> = () => Next<K, V>;