loopus-lazy v1.3.2
Lazy collections for efficient in-memory data queries
Introduction
When working with in-memory data, a common practice is to use Array-like objects and chain calls to filter(), map() or reduce() methods.
Problem: each operation in the chain produces a new Array, causing as many unnecessary copy workloads.
Lazy collections defer evaluation of the chain until the very last moment: when data is iterated.
Operations such as filter(), map() or reduce() do not cause intermediate copy workloads, making the whole chain more efficient.
Basic example
import { Collection } from "loopus-lazy";
const collection = Collection.from([" Hello ", " World! "]) // Use an Array as source - could be any Iterable object
.map((s) => s.trim()) // No operation executed (yet)
.map((s) => s.toLowerCase()) // No operation executed (yet)
.filter((s) => s === "hello" || s === "world!"); // No operation executed (yet)
for (let s of collection) {
// Operations are evaluated here
// hello
// world
}Get a Collection<T> object
Collection.from<T>(iterable: Iterable<T>): Collection<T>
Array-like methods
concat(...others: Iterable<T>[]): Collection<T>every(callback: Filter<T>): booleanfilter(callback: Filter<T>): Collection<T>find(callback: Filter<T>): T | undefinedincludes(searchElement: T, equalityComparer?: EqualityComparer<T>): booleanmap<M>(callback: Mapper<T, M>): Collection<M>reduce<R>(callback: Reducer<T, R>, initialValue: R): Rsome(callback: Filter<T>): boolean
Comparers
Comparers.defaultComparers.caseInsensitiveComparers.searchableEqualityComparers.defaultEqualityComparers.caseInsensitiveEqualityComparers.searchable
Grouping
groupBy<K>(keySelector: Mapper<T, K>): Collection<Group<T, K>>const values = Collection.from([ { fruit: "Apple", color: "Red", }, { fruit: "Banana", color: "Yellow", }, { fruit: "Cherry", color: "Red", }, { fruit: "Tomato", color: "Red", }, { fruit: "Orange", color: "Orange", }, ]); const result = values .groupBy((x) => x.color) .map((g) => ({ color: g.key, count: g.count() })) // g is a Collection .toArray(); expect(result).toStrictEqual([ { color: "Red", count: 3 }, { color: "Yellow", count: 1 }, { color: "Orange", count: 1 }, ]);
Join & Merge
join(separator?: string): stringconst values = Collection.from(["hello", "world", "!"]); const result = values.join(); expect(result).toBe("hello world !");mergeMap<M>(callback: Mapper<T, Iterable<M>>): Collection<M>const values = Collection.from([ [1, 2, 3], [4, 5, 6], [7, 8, 9], ]); const result = values.mergeMap((x) => x).toArray(); expect(result).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
Pagination
skip(count: number): Collection<T>take(count: number): Collection<T>const pageSize = 25; function getPage<T>(data: Iterable<T>, pageIndex: number): Iterable<T> { return Collection.from(data) .skip(pageIndex * pageSize) .take(pageSize); }
Sorting
orderBy<K>(keySelector: Selector<T, K>, mode: "asc" | "desc" = "asc", keyComparer?: Comparer<K>): Collection<T>thenBy<K>(keySelector: Selector<T, K>, mode: "asc" | "desc" = "asc", keyComparer?: Comparer<K>): Collection<T>const values = Collection.from([ { firstName: "Tyrell", lastName: "WELLICK", expectedOrder: 3, }, { firstName: "Angela", lastName: "MOSS", expectedOrder: 2, }, { firstName: "Elliot", lastName: "ALDERSON", expectedOrder: 1, }, { firstName: "Darlene", lastName: "ALDERSON", expectedOrder: 0, }, ]); const result = values .orderBy((x) => x.lastName) .thenBy((x) => x.firstName) .map((x) => x.expectedOrder) .toArray(); expect(result).toStrictEqual([0, 1, 2, 3]);
Utils
average(): number | undefinedcount(): numberfirst(): T | undefinedmin(): number | undefinedmax(): number | undefinedsum(): numbertoArray(): Array<T>