npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

lazystream.ts

v0.5.7

Published

LazyStream.TS provides an easy way to work with collections in FP-like and SQL-like styles.

Downloads

3

Readme

LazyStream.TS

Inspired by Java 8 Streams and .NET LINQ, this small library provides an easy way to work with collections in FP-like and SQL-like styles.

Class: Stream <T>

Stream class that wraps Iterable<T> and provides most of the common FP-style operations like map, filter, flatMap etc. as well as SQL-style select, where, join etc. Stream does also implement Iterable<T> so it can wrap other stream, and since most of the operations return Stream<T>, the calls can be easily chained with each other, for example:

const numbers: Array<number> = ...
const evenSquares = new Stream(numbers)
   .filter(v => v % 2 == 0)
   .map(v => v * v)
   .toArray();

Types can be primitives (as in the example above) but can also be Objects, so SQL-like instructions can be used:

const users: Array<{name: string, age: number, city: string}> = ...
const usersByCity = new Stream(users)
  .where("age", ">=", 25)
  .groupBy("city")
  .toArray();

Type parameters

T

Type of elements in the stream. Can be any type including Object, primitives, Iterable etc.

Summary of operations

FP-style

  • filter
  • map
  • reduce
  • flat
  • flatMap

SQL-style

  • groupBy
  • join
  • select
  • where

Collectors

  • forEach
  • toArray
  • toMap

Shortcuts

  • last
  • max
  • min

Constructors

constructor

+ new Stream(iterableOrIteratorFactory: Iterable‹T› | function): Stream

Defined in index.ts:149

Creates a new instance of Stream by wrapping existing Iterable<T> or just a function that returns Iterator<T> (so generator function can be passed as well). For example:

// from Iterable<T>
const fromIterable = new Stream([1,2,3,4]);

// from () => Iterator<T>
function* generator() {
  yield 1;
  yield 2;
  yield 3;
}
const fromGenerator = new Stream(generator);

Parameters:

Name | Type | Description | ------ | ------ | ------ | iterableOrIteratorFactory | Iterable‹T› | function | instance of Iterable<T> or () => Iterator<T> |

Returns: Stream

Methods

[Symbol.iterator]

[Symbol.iterator](): Iterator‹T›

Defined in index.ts:179

Returns: Iterator‹T›


filter

filter(predicate: function): Stream‹T›

Defined in index.ts:210

Filters elements given a predicate function. Example of usage:

const evens = new Stream([1, 2, 3])
  .filter(i => i % 2 == 0)
  .toArray();

expect(even).toStrictEqual([2]);

Parameters:

predicate: function

function that accepts element and return true or false

▸ (t: T): boolean

Parameters:

Name | Type | ------ | ------ | t | T |

Returns: Stream‹T›


flat

flat(this: Stream‹Iterable‹any››): Stream‹T extends Iterable ? E : never›

Defined in index.ts:238

Flattens elements of this Stream<Iterable<T>> into Stream<T>. Example of usage:

const flattened = new Stream([[1,3], [2,4]])
   .flat()
   .toArray();

expect(flattened).toStrictEqual([1, 3, 2, 4]);

Parameters:

Name | Type | ------ | ------ | this | Stream‹Iterable‹any›› |

Returns: Stream‹T extends Iterable ? E : never›


flatMap

flatMap<K>(field: K): Stream‹Val<T, K> extends Iterable ? E : never›

Defined in index.ts:259

First maps elements of Stream<T> to Stream<Iterable<R>> and then flattens into Stream<R>. For example:

const flattened = new Stream([{numbers: [1, 3]}, {numbers: [2, 4]}])
  .flatMap("numbers") 
  .toArray();
// "numbers" - name of a field that contains Iterable

expect(flattened).toStrictEqual([1, 3, 2, 4]);

Type parameters:

K: FieldOrFn‹T›

Parameters:

Name | Type | Description | ------ | ------ | ------ | field | K | field extractor see FieldOrFn<T> |

Returns: Stream‹Val<T, K> extends Iterable ? E : never›


forEach

forEach(fn: Fn‹T›): void

Defined in index.ts:562

Fetches all elements from the stream and executes given function for each element. Example of usage:

var sum = 0;
new Stream([1, 2, 3])
  .forEach(v => sum += v);

expect(sum).toStrictEqual(6);

Parameters:

Name | Type | Description | ------ | ------ | ------ | fn | Fn‹T› | function to invoke |

Returns: void


groupBy

groupBy<K>(keyFieldOrFn?: K): Stream‹object›

Defined in index.ts:516

Mimics SQL GROUP BY operator. Groups elements with the same given key. Keys must be in a sorted order, otherwise will raise an exception. Next element is emitted only once the element with the next key appears in the stream. Example of usage:

const ungrouped = [{a: 1, b: "val 1"}, {a: 1, b: "val 2"}, 
                   {a: 2, b: "val 3"}, {a: 2, b: "val 4"}];
const grouped = new Stream(ungrouped)
  .groupBy("a")
  .toArray();

expect(grouped).toStrictEqual([
  {key: 1, values: [{a: 1, b: "val 1"}, {a: 1, b: "val 2"}]},
  {key: 2, values: [{a: 2, b: "val 3"}, {a: 2, b: "val 4"}]}
]);

Type parameters:

K: FieldOrFn‹T›

Parameters:

Name | Type | Description | ------ | ------ | ------ | keyFieldOrFn? | K | |

Returns: Stream‹object›


join

join<O, KC, KL, KR, JT>(other: Iterable‹O›, params: object): Stream‹JoinEntry‹T, O, JT››

Defined in index.ts:369

Mimics SQL JOIN operator. Depending on type of join, for each element of source stream lookups a corresponding element from joined stream, using join parameter that can either be a field, or a function.

If using SORTED join type, it will ensure that keys from both set come in the specified order, otherwise will raise an exception. This is the most intended usage of this operation as it won't need to pre-fetch all elements from second stream in memory. The output keys order is preserved, i.e. if join order is ascending, then join entries will be emitted with the keys being in ascending order.

If using UNSORTED join type, it will pre-fetch all elements from second stream into a hash map before any join entries can be emitted.

Keys are not required to be unique, for duplicate keys, join entries will be multiplied, like it happens in SQL:

[1,2,2] left join [2,2,3] = [{1,null}, {2,2}, {2,2}, {2,2}, {2,2}]

Example of usage:

let collectionA = [{a: 1, b: "val 1",}, {a: 2, b: "val 2",}, {a: 3, b: "val 3",}];
let collectionB = [{a: 1, b: "val a",}, {a: 2, b: "val b",}];
const joined = new Stream(collectionA)
  .join(collectionB, {joinType: JoinType.INNER_ASC, commonKey: "a"})
  .toArray();

expect(result).toStrictEqual([
  {key: 1, left: {a: 1, b: "val 1"}, right: {a: 1, b: "val a"}},
  {key: 2, left: {a: 2, b: "val 2"}, right: {a: 2, b: "val b"}}
]);

Type parameters:

O - type of elements in the other stream being joined

Parameters:

other: Iterable‹O› - other stream to join (right-side)

params: Optional object= {joinType?, commonKey?, leftKey?, rightKey?}

Name | Type | Description | ------ | ------------ | ----------------------- | commonKey? | FieldOrFn‹T | O› | Common field that belongs to both streams elements, or a function that can extract key from T | O; if provided, next 2 will be ignored. | leftKey? | FieldOrFn‹O› | Field that belongs to current (left) stream elements, or a function that can extract key from T. If not provided, then elements will be used as keys and are supposed to be primitive. | rightKey? | JoinType | Field that belongs to other (right) stream elements, or a function that can extract key from O. If not provided, then elements will be used as keys and are supposed to be primitive. | joinType? | FieldOrFn‹T› | Join mode, default value is JoinType.INNER_ASC. |

JoinType is defining a semantic of a join operation as follows:

JoinType | Left | Right | Result | -------- | ------- | ---- | ----| INNER_ASC | [1,2] | [2,3] | [{key: 2, left: 2, right: 2}] | LEFT_ASC | [1,2] | [2,3] | [{key: 1, left: 2, right: null}, {key: 2, left: 2, right: 2}] | RIGHT_ASC | [1,2] | [2,3] | [{key: 2, left: 2, right: 2}, {key: 3, left: null, right: 3}] | FULL_ASC | [1,2] | [2,3] | [{key: 1, left: 1, right: null}, {key: 2, left: 2, right: 2}, {key: 3, left: null, right: 3}] | INNER_DESC | [2,1] | [3,2] | [{key: 2, left: 2, right: 2}] | LEFT_DESC | [2,1] | [3,2] | [{key: 2, left: 2, right: 2}, {key: 1, left: 2, right: null}] | RIGHT_DESC | [2,1] | [3,2] | [{key: 3, left: 3, right: null}, {key: 2, left: 2, right: 2}] | FULL_DESC | [2,1] | [3,2] | [{key: 3, left: 3, right: null}, {key: 2, left: 2, right: 2}, {key: 1, left: 2, right: null}] | INNER_UNSORTED | [1,3,2] | [2,1,4] | [{key: 1, left: 2, right: 1}, {key: 2, left: 2, right: 2}] LEFT_UNSORTED | [1,3,2] | [2,1,4] | [{key: 1, left: 2, right: 1}, {key: 3, left: null, right: 3}, {key: 2, left: 2, right: 2}]

Returns: Stream‹JoinEntry‹T, O, JT››


last

last(): T

Defined in index.ts:638

Fetches all elements from the stream and returns the last element. Example of usage:

const result = new Stream([1, 2, 3]).last();
expect(result).toStrictEqual(3);

Returns: T


map

map<R>(mapFn: function): Stream‹R›

Defined in index.ts:225

Maps each element of a current stream with a mapper function and returns new Stream of newly created elements. Example of usage:

const squares = new Stream([1, 2, 3])
  .map(i => i * i)
  .toArray();

Type parameters:

R

Parameters:

mapFn: function

function that accepts current element and returns a new one. The function can optionally accept prev element (original and mapped one).

▸ (t: T, prevT?: T, prevR?: R): R

Parameters:

Name | Type | ------ | ------ | t | T | prevT? | T | prevR? | R |

Returns: Stream‹R›


max

max(this: Stream‹number›): number

Defined in index.ts:664

Fetches all elements from the stream and returns the maximal one. Example of usage:

const result = new Stream([1, 2, 3]).max();
expect(result).toStrictEqual(3);

Currently only supports numeric streams, proper comparator support to be added soon.

Parameters:

Name | Type | ------ | ------ | this | Stream‹number› |

Returns: number


min

min(this: Stream‹number›): number

Defined in index.ts:651

Fetches all elements from the stream and returns the minimal one. Example of usage:

const result = new Stream([1, 2, 3]).min();
expect(result).toStrictEqual(1);

Currently only supports numeric streams, proper comparator support be added soon.

Parameters:

Name | Type | ------ | ------ | this | Stream‹number› |

Returns: number


reduce

reduce<R>(reduceFn: function): R

Defined in index.ts:618

Fetches all elements from the stream and recursively applies reduceFn to each element providing previous result to each call. Example of usage:

const result = new Stream([1, 2, 3])
 .reduce<number>((a, b) => (a === undefined ? 0 : a) + b);

expect(result).toStrictEqual(6);

Type parameters:

R

Parameters:

reduceFn: function

function(accumulator: R | undefined, current: T, index: number) => R

▸ (accumulator: R | undefined, current: T, index: number): R

Parameters:

Name | Type | ------ | ------ | accumulator | R | undefined | current | T | index | number |

Returns: R


select

select<U1, U2>(field1: U1, ...field2: U2[]): Stream‹[U2] extends [never] ? T[U1] : object›

Defined in index.ts:283

Mimics SQL SELECT operator, by restricting set of fields that need be returned. Accepts list of field names, and returns objects with only those fields, for example:

const selectedAB = stream([{a: 1, b: "str", c: 3}]).select("a", "b");
const selectedA = stream([{a: 1, b: "str", c: 3}]).select("a");

expect(selectedAB).toStrictEqual([{a: 1, b: "str"}]);
expect(selectedA).toStrictEqual([1]);

Type parameters:

U1: Field‹T›

U2: Field‹T›

Parameters:

Name | Type | Description | ------ | ------ | ------ | field1 | U1 | field name | ...field2 | U2[] | field name (none or many) |

Returns: Stream‹[U2] extends [never] ? T[U1] : object›


toArray

toArray(): Array‹T›

Defined in index.ts:571

Fetches all elements from the stream and collect them int Array<T>.

Returns: Array‹T›


toMap

toMap<K, V>(key: K, val?: V): Map‹Val‹T, K›, Val‹T, V››

Defined in index.ts:594

Fetches all elements from the stream and collect them int Map<K, V>. Example of usage:

const result = new Stream([1, 2, 3])
  .toMap(t => `${t}`);

expect(result).toStrictEqual(new Map([['1', 1], ['2', 2], ['3', 3]]));

Type parameters:

K: FieldOrFn‹T›

V: FieldOrFn‹T›

Parameters:

Name | Type | Description | ------ | ------ | ------ | key | K | key field or function | val? | V | value field or function |

Returns: Map‹Val‹T, K›, Val‹T, V››


where

where<K>(field: K, compareOp: ComparisonOp, value: Val‹T, K›): Stream‹T›

Defined in index.ts:314

Mimics SQL WHERE clause, by including only the records that satisfy given parameters. Example of usages:

const objs = [{a: 1, b: "val a", c: 3}, {a: 2, b: "val b", c: 4}, 
              {a: 3, b: "val c", c: 4}];
const result = new Stream(objs)
  .where("a", "<", 3)
  .where("b", "!=", "val a")
  .toArray();

expect(result).toStrictEqual([{a: 2, b: "val b", c: 4}]);

Type parameters:

K: FieldOrFn‹T›

Parameters:

Name | Type | Description | ------ | ------ | ------ | field | K | field name, see Field<T> | compareOp | ComparisonOp | comparison operation, see ComparisonOp | value | Val‹T, K› | value of type T[Field] to compare with |

Returns: Stream‹T›

Creating streams from existing collections

from

from<T>(first: Iterable‹T›, second: Iterable‹T›, ...rest: Iterable‹T›[]): Stream‹T[]›

Defined in index.ts:21

Cross-multiplies multiple Iterable's of the same type T into Stream<T[]>. Can accept any number of args. This function can be used as a shortcut - from(someIterable) instead of new Stream(someIterable).

Example of usage:

const result = from([1, 3], [2, 4])
  .toArray();

expect(result).toStrictEqual([[1, 3], [1, 4], [2, 3], [2, 4]]);

Type parameters:

T

Parameters:

Name | Type | Description | ------ | ------ | ------ | first | Iterable‹T› | (required) first Iterable | second | Iterable‹T› | (optional) second Iterable | ...rest | Iterable‹T›[] | (optional) other Iterables |

Returns: Stream‹T[]›


range

range(from: number, to: number): Stream‹number›

Defined in index.ts:60

Creates a Stream<number> with all numbers from the range. Example of usage:

const result = range(0, 10)
  .toArray();

expect(result).toStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

Parameters:

Name | Type | Description | ------ | ------ | ------ | from | number | start of range (inclusive) | to | number | end of range (inclusive) |

Returns: Stream‹number›