jsiq
v0.3.0
Published
Dotnet LINQ inspired query methods for iterators
Downloads
3
Readme
JS Iterator Queries
Inspired by dotnet LINQ I decided to adopt it to use with ES6 iterators.
Usage
Embedding
All methods are implemented as pure functions. And you can always use then as is.
But for convenience and more readable code jsiq
provides ability to embed methods to native JS iterable classes: Array
, Set
, Map
.
After calling the embed
method, you can start call jsiq
methods right from your collections:
require('jsiq/lib/embed')();
const personsArray = await loadPersonsAsync();
const underageIterator = personsArray.where(p => p.age < 18);
Chaining
All methods can be chained to build complex queries on your collections:
require('jsiq/lib/embed')();
const personsArray = await loadPersonsAsync();
const reportItems = personsArray
.where(p => p.age > 18)
.where(p => p.children && p.children.length > 0)
.select(p => ({
name: p.name,
childrenCount: p.children ? p.children.length : 0,
isMarried: !!(p.wife || p.husband)
}))
.orderBy(p => p.childrenCount)
.toArray();
Basic usage
And you still can use all methods directly by passing iterators:
const { where, toArray } = require('jsiq');
const personsMap = getPersonsMap();
const underage = toArray(where(personsMap.values(), p => p.age < 18));
Methods
where
Filters a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.
Signature:
where<T>(
source: Iterator<T> | Iterable<T>,
predicate: (item: T, index: Number) => boolean
) => IterableIterator<T>
Basic example:
const adultsQuery = where(personsArray, p => p.age > 18);
Embedded example:
const adultsQuery = personsArray.where(p => p.age > 18);
select
Projects each element of a sequence into a new form.
Signature:
select<T, TResult>(
source: Iterator<T> | Iterable<T>,
predicate: (item: T) => TResult
) => IterableIterator<TResult>
Basic example:
const idsQuery = select(personsArray, p => p.id);
Embedded example:
const idsQuery = personsArray.select(p => p.id);
concat
Concatenates two sequences.
Signature:
concat<T>(
source: Iterator<T> | Iterable<T>,
appendix: Iterator<T> | Iterable<T>
) => IterableIterator<T>
Basic example:
const personsQuery = concat(childrenQuery, adultsQuery);
Embedded example:
const personsQuery = childrenQuery.concat(adultsQuery);
distinct
Returns distinct elements from a sequence.
Signatures:
distinct<T>(
source: Iterator<T>
) => IterableIterator<T>
distinct<T, TValue>(
source: Iterator<T> | Iterable<TSource>,
selector: (item: T) => TValue
) => IterableIterator<T>
Basic example:
const studentsQuery = distinct(studentsFromGroups);
const personsWithUniqueName = distinct(persons, p => p.name);
Embedded example:
const studentsQuery = studentsFromGroups.distinct();
const personsWithUniqueName = persons.distinct(p => p.name);
take
Returns a specified number of contiguous elements from the start of a sequence.
Signature:
take<T>(
source: Iterator<T> | Iterable<T>,
count: number
) => IterableIterator<T>
Basic example:
const first2 = take(personsArray, 2);
Embedded example:
const first2 = personsArray.take(2);
takeWhile
Returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function.
Signature:
takeWhile<T>(
source: Iterator<T> | Iterable<T>,
predicate: (item: T, index: Number) => boolean
) => IterableIterator<T>
Basic example:
const untilFirstFail = takeWhile(attempts, at => at.success);
Embedded example:
const untilFirstFail = attempts.takeWhile(at => at.success);
skip
Bypasses a specified number of elements in a sequence and then returns the remaining elements
Signature:
skip<T>(
source: Iterator<T> | Iterable<T>,
count: number
) => IterableIterator<T>
Basic example:
const excludeFirst2 = skip(personsArray, 2);
Embedded example:
const excludeFirst2 = personsArray.skip(2);
skipWhile
Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. The element's index is used in the logic of the predicate function.
Signature:
skipWhile<T>(
source: Iterator<T> | Iterable<T>,
predicate: (item: T, index: Number) => boolean
) => IterableIterator<T>
Basic example:
const afterFirstFail = skipWhile(attempts, at => at.success);
Embedded example:
const afterFirstFail = attempts.skipWhile(at => at.success);
aggregate
Applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value.
Signatures:
aggregate<TSource>(
source: Iterator<TSource> | Iterable<TSource>,
fn: (acc: TSource, item: TSource) => TSource
) => TSource;
aggregate<TSource, TResult>(
source: Iterator<TSource> | Iterable<TSource>,
fn: (acc: TSource, item: TSource) => TSource,
resultSelector: (acc: TSource) => TResult
) => TResult;
aggregate<TSource, TAccumulate>(
source: Iterator<TSource> | Iterable<TSource>,
seed: TAccumulate,
fn: (acc: TAccumulate, item: TSource) => TAccumulate
) => TAccumulate;
aggregate<TSource, TAccumulate, TResult>(
source: Iterator<TSource> | Iterable<TSource>,
seed: TAccumulate,
fn: (acc: TAccumulate, item: TSource) => TAccumulate,
resultSelector: (acc: TAccumulate) => TResult
) => TResult;
Basic example:
const sum = aggregate(integers, (sum, i) => sum + i);
const sumSquare = aggregate(integers, (sum, i) => sum + i, sum => sum * sum);
const totalSpent = aggregate(personsQuery, 0, (sum, p) => sum + p.spent);
const avgAge = aggregate(personsQuery,
{ ageSum: 0, count: 0 },
({ ageSum, count }, p) => ({ ageSum: p.age + ageSum, count: count + 1 }),
({ ageSum, count }) => ageSum / count
);
Embedded example:
const sum = integers.aggregate((sum, i) => sum + i);
const sumSquare = integers.aggregate((sum, i) => sum + i, sum => sum * sum);
const totalSpent = personsQuery.aggregate(0, (sum, p) => sum + p.spent);
const avgAge = personsQuery.aggregate(
{ ageSum: 0, count: 0 },
({ ageSum, count }, p) => ({ ageSum: p.age + ageSum, count: count + 1 }),
({ ageSum, count }) => ageSum / count
);
toArray
Creates an Array
from iterator values.
Signature:
toArray<T>(source: Iterator<T>) => T[]
Basic example:
const personsArray = toArray(personsQuery);
Embedded example:
const personsArray = personsQuery.toArray();
toSet
Creates a Set
from iterator values.
Signature:
toSet<T>(source: Iterator<T>) => Set<T>
Basic example:
const names = toSet(select(personQuery, p => p.name));
Embedded example:
const names = personsQuery.select(p => p.name).toSet();
toMap
Creates a Map
according to a specified key selector function and an value selector function.
Signatures:
toMap<TKey, TValue>(source: Iterator<[TKey, TValue]>) => Map<TKey, TValue>
toMap<T, TKey>(
source: Iterator<T>,
keySelector: (item: T) => TKey
) => Map<TKey, T>
toMap<T, TKey, TValue>(
source: Iterator<T>,
keySelector: (item: T) => TKey,
valueSelector: (item: T) => TValue
) => Map<TKey, TValue>
Basic example:
const persons = toMap(personQuery, p => p.id);
const names = toMap(personQuery, p => p.id, p => p.name);
Embedded example:
const persons = personQuery.toMap(p => p.id);
const names = personQuery.toMap(p => p.id, p => p.name);