Inspired by Python — designed for TypeScript.
IterTools makes you an iteration superstar by providing two types of tools:
- Loop iteration tools
- Stream iteration tools
- Pipe iteration tools
Loop Iteration Tools Example
import { multi } from 'itertools-ts';
for (const [letter, number] of multi.zip(['a', 'b'], [1, 2])) {
console.log(`${letter}${number}`); // a1, b2
}
// Async example
const letters = ['a', 'b'].map((x) => Promise.resolve(x));
const numbers = [1, 2].map((x) => Promise.resolve(x));
for await (const [letter, number] of multi.zipAsync(letters, numbers)) {
console.log(`${letter}${number}`); // a1, b2
}
Stream Iteration Tools Example
import { Stream, AsyncStream } from 'itertools-ts';
const result1 = Stream.of([1, 1, 2, 2, 3, 4, 5])
.distinct() // [1, 2, 3, 4, 5]
.map((x) => x**2) // [1, 4, 9, 16, 25]
.filter((x) => x < 10) // [1, 4, 9]
.toSum(); // 14
// Async example
const result2 = await AsyncStream.of([1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x)))
.distinct() // [1, 2, 3, 4, 5]
.map((x) => x**2) // [1, 4, 9, 16, 25]
.filter((x) => x < 10) // [1, 4, 9]
.toSum(); // 14
Pipe Iteration Tools Example
import { createPipe } from 'itertools-ts';
const pipe = createPipe(
set.distinct<number>,
(input) => single.map(input, (x) => x**2),
(input) => single.filter(input, (x) => x < 10),
reduce.toSum,
);
const result1 = pipe([1, 1, 2, 2, 3, 4, 5]); // 14
const result2 = pipe([1, 1, 1, 2, 2, 2]); // 5
// Async example
const asyncPipe = createPipe(
set.distinctAsync<number>,
(input) => single.mapAsync(input, (x) => x**2),
(input) => single.filterAsync(input, (x) => x < 10),
reduce.toSumAsync,
);
const result3 = await asyncPipe([1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x))); // 14
const result4 = await asyncPipe([1, 1, 1, 2, 2, 2].map((x) => Promise.resolve(x))); // 5
// Another way to create pipes
const anotherPipe = createPipe()
.add(set.distinct<number>)
.add((input) => single.map(input, (x) => x**2))
.add((input) => single.filter(input, (x) => x < 10))
.add(reduce.toSum);
const result5 = anotherPipe([1, 1, 2, 2, 3, 4, 5]); // 14
const result6 = anotherPipe([1, 1, 1, 2, 2, 2]); // 5
All functions work on iterable collections and iterators:
Array
Set
Map
String
Generator
Iterable
Iterator
Every function have an analog with "Async"-suffixed name for working with async iterable and iterators (e.g. zip
and zipAsync
):
AsyncIterable
AsyncIterator
If an asynchronous function takes other functions as input, they can also be asynchronous.
import { single } from 'itertools-ts';
const starWarsEpisodes = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for await (const goodMovie of single.filterAsync(
starWarsEpisodes,
async (episode) => {
return Promise.resolve(episode > 3 && episode < 8);
}
)) {
console.log(goodMovie);
}
// 4, 5, 6, 7
npm i itertools-ts
Iterator | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
chain |
Chain multiple iterables together | multi.chain(list1, list2, ...) |
multi.chainAsync(list1, list2, ...) |
zip |
Iterate multiple collections simultaneously until the shortest iterator completes | multi.zip(list1, list2, ...) |
multi.zipAsync(list1, list2, ...) |
zipEqual |
Iterate multiple collections of equal length simultaneously, error if lengths not equal | multi.zipEqual(list1, list2, ...) |
multi.zipEqualAsync(list1, list2, ...) |
zipFilled |
Iterate multiple collections simultaneously until the longest iterator completes (with filler for uneven lengths) | multi.zipFilled(filler, list1, list2, ...) |
multi.zipFilledAsync(filler, list1, list2, ...) |
zipLongest |
Iterate multiple collections simultaneously until the longest iterator completes | multi.zipLongest(list1, list2, ...) |
multi.zipLongestAsync(list1, list2, ...) |
Iterator | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
chunkwise |
Iterate by chunks | single.chunkwise(data, chunkSize) |
single.chunkwiseAsync(data, chunkSize) |
chunkwiseOverlap |
Iterate by overlapped chunks | single.chunkwiseOverlap(data, chunkSize, overlapSize) |
single.chunkwiseOverlapAsync(data, chunkSize, overlapSize) |
compress |
Filter out elements not selected | single.compress(data, selectors) |
single.compressAsync(data, selectors) |
dropWhile |
Drop elements while predicate is true | single.dropWhile(data, predicate) |
single.dropWhileAsync(data, predicate) |
enumerate |
Enumerates elements of collection | single.enumerate(data) |
single.enumerateAsync(data) |
filter |
Filter for elements where predicate is true | single.filter(data, predicate) |
single.filterAsync(data, predicate) |
flatMap |
Map function onto items and flatten result | single.flatMap(data, mapper) |
single.flatMapAsync(data, mapper) |
flatten |
Flatten multidimensional iterable | single.flatten(data, [dimensions]) |
single.flattenAsync(data, [dimensions]) |
groupBy |
Group data by a common element | single.groupBy(data, groupKeyFunction, [itemKeyFunc]) |
single.groupByAsync(data, groupKeyFunction, [itemKeyFunc]) |
limit |
Iterate up to a limit | single.limit(data, limit) |
single.limitAsync(data, limit) |
keys |
Iterate keys of key-value pairs | single.keys(data) |
single.keysAsync(data) |
map |
Map function onto each item | single.map(data, mapper) |
single.mapAsync(data, mapper) |
pairwise |
Iterate successive overlapping pairs | single.pairwise(data) |
single.pairwiseAsync(data) |
repeat |
Repeat an item a number of times | single.repeat(item, repetitions) |
single.repeatAsync(item, repetitions) |
skip |
Iterate after skipping elements | single.skip(data, count, [offset]) |
single.skipAsync(data, count, [offset]) |
slice |
Extract a slice of the iterable | single.slice(data, [start], [count], [step]) |
single.sliceAsync(data, [start], [count], [step]) |
sort |
Iterate a sorted collection | single.sort(data, [comparator]) |
single.sortAsync(data, [comparator]) |
takeWhile |
Iterate elements while predicate is true | single.takeWhile(data, predicate) |
single.takeWhileAsync(data, predicate) |
values |
Iterate values of key-value pairs | single.values(data) |
single.valuesAsync(data) |
Iterator | Description | Code Snippet |
---|---|---|
count |
Count sequentially forever | infinite.count([start], [step]) |
cycle |
Cycle through a collection | infinite.cycle(iterable) |
repeat |
Repeat an item forever | infinite.repeat(item) |
Iterator | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
runningAverage |
Running average accumulation | math.runningAverage(numbers, [initialValue]) |
math.runningAverageAsync(numbers, [initialValue]) |
runningDifference |
Running difference accumulation | math.runningDifference(numbers, [initialValue]) |
math.runningDifferenceAsync(numbers, [initialValue]) |
runningMax |
Running maximum accumulation | math.runningMax(numbers, [initialValue]) |
math.runningMax(numbers, [initialValue]) |
runningMin |
Running minimum accumulation | math.runningMin(numbers, [initialValue]) |
math.runningMinAsync(numbers, [initialValue]) |
runningProduct |
Running product accumulation | math.runningProduct(numbers, [initialValue]) |
math.runningProductAsync(numbers, [initialValue]) |
runningTotal |
Running total accumulation | math.runningTotal(numbers, [initialValue]) |
math.runningTotalAsync(numbers, [initialValue]) |
Reducer | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
toAverage |
Mean average of elements | reduce.toAverage(numbers) |
reduce.toAverageAsync(numbers) |
toCount |
Reduce to length of iterable | reduce.toCount(data) |
reduce.toCountAsync(data) |
toFirst |
Reduce to its first value | reduce.toFirst(data) |
reduce.toFirstAsync(data) |
toFirstAndLast |
Reduce to its first and last values | reduce.toFirstAndLast(data) |
reduce.toFirstAndLastAsync(data) |
toLast |
Reduce to its last value | reduce.toLast(data) |
reduce.toLastAsync(data) |
toMax |
Reduce to its greatest element | reduce.toMax(numbers, [compareBy]) |
reduce.toMaxAsync(numbers, [compareBy]) |
toMin |
Reduce to its smallest element | reduce.toMin(numbers, [compareBy]) |
reduce.toMinAsync(numbers, [compareBy]) |
toMinMax |
Reduce to its lower and upper bounds | reduce.toMinMax(numbers, [compareBy]) |
reduce.toMinMaxAsync(numbers, [compareBy]) |
toProduct |
Reduce to the product of its elements | reduce.toProduct(numbers) |
reduce.toProductAsync(numbers) |
toRange |
Reduce to difference of max and min values | reduce.toRange(numbers) |
reduce.toRangeAsync(numbers) |
toSum |
Reduce to the sum of its elements | reduce.toSum(numbers) |
reduce.toSumAsync(numbers) |
toValue |
Reduce to value using callable reducer | reduce.toValue(data, reducer, initialValue) |
reduce.toValueAsync(data, reducer, initialValue) |
Iterator | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
cartesianProduct |
Iterate cartesian product of iterables | set.cartesianProduct(...iterables) |
set.cartesianProductAsync(...iterables) |
distinct |
Iterate only distinct items | set.distinct(data) |
set.distinctAsync(data) |
intersection |
Intersection of iterables | set.intersection(...iterables) |
set.intersectionAsync(...iterables) |
partialIntersection |
Partial intersection of iterables | set.partialIntersection(minCount, ...iterables) |
set.partialIntersectionAsync(minCount, ...iterables) |
symmetricDifference |
Symmetric difference of iterables | set.symmetricDifference(...iterables) |
set.symmetricDifferenceAsync(...iterables) |
union |
Union of iterables | set.union(...iterables) |
set.unionAsync(...iterables) |
Summary | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
allMatch |
True if all items are true according to predicate | summary.allMatch(data, predicate) |
summary.allMatchAsync(data, predicate) |
allUnique |
True if all elements in collection are unique | summary.allUnique(data) |
summary.allUniqueAsync(data) |
anyMatch |
True if any item is true according to predicate | summary.anyMatch(data, predicate) |
summary.anyMatchAsync(data, predicate) |
exactlyN |
True if exactly n items are true according to predicate | summary.exactlyN(data, n, predicate) |
summary.exactlyNAsync(data, n, predicate) |
isAsyncIterable |
True if given data is async iterable | summary.isAsyncIterable(data) |
— |
isIterable |
True if given data is iterable | summary.isIterable(data) |
— |
isIterator |
True if given data is iterator | summary.isIterator(data) |
— |
isReversed |
True if iterable reverse sorted | summary.isReversed(data) |
summary.isReversedAsync(data) |
isSorted |
True if iterable sorted | summary.isSorted(data) |
summary.isSortedAsync(data) |
isString |
True if given data is string | summary.isString(data) |
summary.isStringAsync(data) |
noneMatch |
True if none of items true according to predicate | summary.noneMatch(data, predicate) |
summary.noneMatchAsync(data, predicate) |
same |
True if collections are the same | summary.same(...collections) |
summary.sameAsync(...collections) |
sameCount |
True if collections have the same lengths | summary.sameCount(...collections) |
summary.sameCountAsync(...collections) |
Iterator | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
tee |
Iterate duplicate iterables | transform.tee(data, count) |
transform.teeAsync(data, count) |
toArray |
Transforms collection to array | transform.toArray(data) |
transform.toArrayAsync(data) |
toAsyncIterable |
Transforms collection to async iterable | transform.toAsyncIterable(data) |
— |
toAsyncIterator |
Transforms collection to async iterator | transform.toAsyncIterator(data) |
— |
toIterable |
Transforms collection to iterable | transform.toIterable(data) |
— |
toIterator |
Transforms collection to iterator | transform.toIterator(data) |
— |
toMap |
Transforms collection to map | transform.toMap(pairs) |
transform.toMapAsync(pairs) |
toSet |
Transforms collection to set | transform.toSet(data) |
transform.toSetAsync(data) |
Source | Description | Sync Code Snippet | Async Code Snippet |
---|---|---|---|
of |
Create a stream from an iterable | Stream.of(iterable) |
AsyncStream.of(iterable) |
ofEmpty |
Create an empty stream | Stream.ofEmpty() |
AsyncStream.ofEmpty() |
ofCount |
Create an infinite count stream | Stream.ofCount([start], [step]) |
AsyncStream.ofCount([start], [step]) |
ofCycle |
Create an infinite cycle stream | Stream.ofCycle(iterable) |
AsyncStream.ofCycle(iterable) |
ofRepeat |
Create an infinite repeating stream | Stream.ofRepeat(item) |
AsyncStream.ofRepeat(item) |
Operation | Description | Code Snippet |
---|---|---|
cartesianProductWith |
Iterate cartesian product of iterable source with another iterable collections | stream.cartesianProductWith(...iterables) |
chainWith |
Chain iterable source withs given iterables together into a single iteration | stream.chainWith(...iterables) |
chunkwise |
Iterate by chunks | stream.chunkwise(chunkSize) |
chunkwiseOverlap |
Iterate by overlapped chunks | stream.chunkwiseOverlap(chunkSize, overlap) |
compress |
Compress source by filtering out data not selected | stream.compress(selectors) |
distinct |
Filter out elements: iterate only unique items | stream.distinct() |
dropWhile |
Drop elements from the iterable source while the predicate function is true | stream.dropWhile(predicate) |
enumerate |
Enumerates elements of stream | stream.enumerate() |
filter |
Filter for only elements where the predicate function is true | stream.filter(predicate) |
flatMap |
Map function onto elements and flatten result | stream.flatMap(mapper) |
flatten |
Flatten multidimensional stream | stream.flatten([dimensions]) |
intersectionWith |
Intersect stream and given iterables | stream.intersectionWith(...iterables) |
groupBy |
Group stram data by a common data element | stream.groupBy(groupKeyFunction, [itemKeyFunc]) |
keys |
Iterate keys of key-value pairs from stream | stream.keys() |
limit |
Limit the stream's iteration | stream.limit(limit) |
map |
Map function onto elements | stream.map(mapper) |
pairwise |
Return pairs of elements from iterable source | stream.pairwise() |
partialIntersectionWith |
Partially intersect stream and given iterables | stream.partialIntersectionWith(minIntersectionCount, ...iterables) |
runningAverage |
Accumulate the running average (mean) over iterable source | stream.runningAverage([initialValue]) |
runningDifference |
Accumulate the running difference over iterable source | stream.runningDifference([initialValue]) |
runningMax |
Accumulate the running max over iterable source | stream.runningMax([initialValue]) |
runningMin |
Accumulate the running min over iterable source | stream.runningMin([initialValue]) |
runningProduct |
Accumulate the running product over iterable source | stream.runningProduct([initialValue]) |
runningTotal |
Accumulate the running total over iterable source | stream.runningTotal([initialValue]) |
skip |
Skip some elements of the stream | stream.skip(count, [offset]) |
slice |
Extract a slice of the stream | stream.slice([start], [count], [step]) |
sort |
Sorts the stream | stream.sort([comparator]) |
symmetricDifferenceWith |
Symmetric difference of stream and given iterables | stream.symmetricDifferenceWith(...iterables) |
takeWhile |
Return elements from the iterable source as long as the predicate is true | stream.takeWhile(predicate) |
unionWith |
Union of stream and given iterables | stream.union(...iterables) |
values |
Iterate values of key-value pairs from stream | stream.values() |
zipWith |
Iterate iterable source with another iterable collections simultaneously | stream.zipWith(...iterables) |
zipEqualWith |
Iterate iterable source with another iterable collections of equal lengths simultaneously | stream.zipEqualWith(...iterables) |
zipFilledWith |
Iterate iterable source with another iterable collections simultaneously (with filler) | stream.zipFilledWith(filler, ...iterables) |
zipLongestWith |
Iterate iterable source with another iterable collections simultaneously | stream.zipLongestWith(...iterables) |
Terminal Operation | Description | Code Snippet |
---|---|---|
tee |
Returns array of multiple identical Streams | stream.tee(count) |
toArray |
Returns array of stream elements | stream.toArray() |
toMap |
Returns map of stream elements (key-value pairs) | stream.toMap() |
toSet |
Returns set of stream elements | stream.toSet() |
Terminal Operation | Description | Code Snippet |
---|---|---|
toAverage |
Reduces stream to the mean average of its items | stream.toAverage() |
toCount |
Reduces stream to its length | stream.toCount() |
toFirst |
Reduces stream to its first value | stream.toFirst() |
toFirstAndLast |
Reduces stream to its first and last values | stream.toFirstAndLast() |
toLast |
Reduces stream to its last value | stream.toLast() |
toMax |
Reduces stream to its max value | stream.toMax([compareBy]) |
toMin |
Reduces stream to its min value | stream.toMin([compareBy]) |
toMin |
Reduce stream to its lower and upper bounds | stream.toMinMax([compareBy]) |
toProduct |
Reduces stream to the product of its items | stream.toProduct() |
toRange |
Reduces stream to difference of max and min values | stream.toRange() |
toSum |
Reduces stream to the sum of its items | stream.toSum() |
toValue |
Reduces stream like array.reduce() function | stream.toValue(reducer, initialValue) |
Terminal Operation | Description | Code Snippet |
---|---|---|
allMatch |
Returns true if all items in stream match predicate | stream.allMatch(predicate) |
allUnique |
Returns true if all elements of stream are unique | stream.allUnique(predicate) |
anyMatch |
Returns true if any item in stream matches predicate | stream.anyMatch(predicate) |
exactlyN |
Returns true if exactly n items are true according to predicate | stream.exactlyN(n, predicate) |
isReversed |
Returns true if stream is sorted in reverse descending order | stream.isReversed() |
isSorted |
Returns true if stream is sorted in ascending order | stream.isSorted() |
noneMatch |
Returns true if none of the items in stream match predicate | stream.noneMatch(predicate) |
sameWith |
Returns true if stream and all given collections are the same | stream.sameWith(...collections) |
sameCountWith |
Returns true if stream and all given collections have the same lengths | stream.sameCountWith(...collections) |
Debug Operation | Description | Code Snippet |
---|---|---|
peek |
Peek at each element between stream operations | stream.peek(peekFunc) |
peekStream |
Peek at the entire stream between operations | stream.peekStream(peekFunc) |
Chain multiple iterables together into a single continuous sequence.
function* chain<T>(
...iterables: Array<Iterable<T> | Iterator<T>>
): Iterable<T>
import { multi } from 'itertools-ts';
const prequels = ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith'];
const originals = ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi'];
for (const movie of multi.chain(prequels, originals)) {
console.log(movie);
}
// 'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith', 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi'
Iterate multiple iterable collections simultaneously.
function* zip<T extends Array<Iterable<unknown> | Iterator<unknown>>>(
...iterables: T
): Iterable<ZipTuple<T, never>>
import { multi } from 'itertools-ts';
const languages = ['PHP', 'Python', 'Java', 'Go'];
const mascots = ['elephant', 'snake', 'bean', 'gopher'];
for (const [language, mascot] of multi.zip(languages, mascots)) {
console.log(`The ${language} language mascot is an ${mascot}.`);
}
// The PHP language mascot is an elephant.
// ...
Zip works with multiple iterable inputs - not limited to just two.
import { multi } from 'itertools-ts';
const names = ['Ryu', 'Ken', 'Chun Li', 'Guile'];
const countries = ['Japan', 'USA', 'China', 'USA'];
const signatureMoves = ['hadouken', 'shoryuken', 'spinning bird kick', 'sonic boom'];
for (const [name, country, signatureMove] of multi.zip(names, countries, signatureMoves)) {
const streetFighter = new StreetFighter(name, country, signatureMove);
}
Note: For uneven lengths, iteration stops when the shortest iterable is exhausted.
Iterate multiple iterable collections simultaneously.
function* zipFilled<T extends Array<Iterable<unknown> | Iterator<unknown>>, F>(
filler: F,
...iterables: T
): Iterable<ZipTuple<T, F>>
For uneven lengths, the exhausted iterables will produce filler
value for the remaining iterations.
import { multi } from 'itertools-ts';
const letters = ['A', 'B', 'C'];
const numbers = [1, 2];
for (const [letter, number] of multi.zipFilled('filler', letters, numbers)) {
// ['A', 1], ['B', 2], ['C', 'filler']
}
Iterate multiple iterable collections simultaneously.
function* zipLongest<T extends Array<Iterable<unknown> | Iterator<unknown>>>(
...iterables: T
): Iterable<ZipTuple<T, undefined>>
For uneven lengths, the exhausted iterables will produce undefined
for the remaining iterations.
import { multi } from 'itertools-ts';
const letters = ['A', 'B', 'C'];
const numbers = [1, 2];
for (const [letter, number] of multi.zipLongest(letters, numbers)) {
// ['A', 1], ['B', 2], ['C', undefined]
}
Iterate multiple iterable collections with equal lengths simultaneously.
Throws LengthException
if lengths are not equal, meaning that at least one iterator ends before the others.
function* zipEqual<T extends Array<Iterable<unknown> | Iterator<unknown>>>(
...iterables: T
): Iterable<ZipTuple<T, never>>
import { multi } from 'itertools-ts';
const letters = ['A', 'B', 'C'];
const numbers = [1, 2, 3];
for (const [letter, number] of multi.zipEqual(letters, numbers)) {
// ['A', 1], ['B', 2], ['C', 3]
}
Return elements in chunks of a certain size.
function* chunkwise<T>(
data: Iterable<T>|Iterator<T>,
chunkSize: number,
): Iterable<Array<T>>
Chunk size must be at least 1.
import { single } from 'itertools-ts';
const movies = [
'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith',
'A New Hope', 'Empire Strikes Back', 'Return of the Jedi',
'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker',
];
const trilogies = [];
for (const trilogy of single.chunkwise(movies, 3)) {
trilogies.push(trilogy);
}
// [
// ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith'],
// ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi'],
// ['The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker]',
// ]
Return overlapped chunks of elements.
function* chunkwiseOverlap<T>(
data: Iterable<T>|Iterator<T>,
chunkSize: number,
overlapSize: number,
includeIncompleteTail: boolean = true,
): Iterable<Array<T>>
- Chunk size must be at least 1.
- Overlap size must be less than chunk size.
import { single } from 'itertools-ts';
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (const chunk of single.chunkwiseOverlap(numbers, 3, 1)) {
// [1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]
}
Compress an iterable by filtering out data that is not selected.
function* compress<T>(
data: Iterable<T> | Iterator<T>,
selectors: Iterable<number|boolean> | Iterator<number|boolean>
): Iterable<T>
import { single } from 'itertools-ts';
const movies = [
'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith',
'A New Hope', 'Empire Strikes Back', 'Return of the Jedi',
'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'
];
const goodMovies = [0, 0, 0, 1, 1, 1, 1, 0, 0];
for (const goodMovie of single.compress(movies, goodMovies)) {
console.log(goodMovie);
}
// 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi', 'The Force Awakens'
Drop elements from the iterable while the predicate function is true.
Once the predicate function returns false once, all remaining elements are returned.
function* dropWhile<T>(
data: Iterable<T>|Iterator<T>,
predicate: (item: T) => boolean
): Iterable<T>
import { single } from 'itertools-ts';
const scores = [50, 60, 70, 85, 65, 90];
const predicate = (x) => x < 70;
for (const score of single.dropWhile(scores, predicate)) {
console.log(score);
}
// 70, 85, 65, 90
Enumerates elements of given collection.
function* enumerate<T>(data: Iterable<T>|Iterator<T>): Iterable<[number, T]>
import { single } from 'itertools-ts';
const letters = ['a', 'b', 'c', 'd', 'e'];
for (const item of single.enumerate(letters)) {
// [[0, 'a'], [1, 'b'], [2, 'c'], [3, 'd'], [4, 'e']]
}
Filter out elements from the iterable only returning elements where the predicate function is true.
function* filter<T>(
data: Iterable<T>|Iterator<T>,
predicate: (datum: T) => boolean,
): Iterable<T>
import { single } from 'itertools-ts';
const starWarsEpisodes = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const goodMoviePredicate = (episode) => episode > 3 && episode < 8;
for (const goodMovie of single.filter(starWarsEpisodes, goodMoviePredicate)) {
console.log(goodMovie);
}
// 4, 5, 6, 7
Map a function only the elements of the iterable and then flatten the results.
function* flatMap<TInput, TOutput>(
data: Iterable<TInput>|Iterator<TInput>,
mapper: FlatMapper<TInput, TOutput>,
): Iterable<TOutput>
import { single } from 'itertools-ts';
const data = [1, 2, 3, 4, 5];
const mapper = (item) => [item, -item];
for (number of single.flatMap(data, mapper)) {
console.log(number);
}
// 1 -1 2 -2 3 -3 4 -4 5 -5
Flatten a multidimensional iterable.
function* flatten(
data: Iterable<unknown>|Iterator<unknown>,
dimensions: number = Infinity,
): Iterable<unknown>
import { single } from 'itertools-ts';
const multidimensional = [1, [2, 3], [4, 5]];
const flattened = [];
for (const number of single.flatten(multidimensional)) {
flattened.push(number);
}
// [1, 2, 3, 4, 5]
Group data by a common data element.
Iterate pairs of group name and collection of grouped items.
function* groupBy<T>(
data: Iterable<T> | Iterator<T>,
groupKeyFunction: (item: T) => string,
itemKeyFunction?: (item: T) => string,
): Iterable<[string, Array<T>] | [string, Record<string, T>]>
- The
groupKeyFunction
determines the key to group elements by. - The optional
itemKeyFunction
allows custom indexes within each group member. - Collection of grouped items may be an array or an object (depends on presence of
itemKeyFunction
param).
import { single } from 'itertools-ts';
const cartoonCharacters = [
['Garfield', 'cat'],
['Tom', 'cat'],
['Felix', 'cat'],
['Heathcliff', 'cat'],
['Snoopy', 'dog'],
['Scooby-Doo', 'dog'],
['Odie', 'dog'],
['Donald', 'duck'],
['Daffy', 'duck'],
];
const charactersGroupedByAnimal = {};
for (const [animal, characters] of single.groupBy(cartoonCharacters, (x) => x[1])) {
charactersGroupedByAnimal[animal] = characters;
}
/*
{
cat: [
['Garfield', 'cat'],
['Tom', 'cat'],
['Felix', 'cat'],
['Heathcliff', 'cat'],
],
dog: [
['Snoopy', 'dog'],
['Scooby-Doo', 'dog'],
['Odie', 'dog'],
],
duck: [
['Donald', 'duck'],
['Daffy', 'duck'],
],
}
*/
Iterate keys of key-value pairs.
function* keys<TKey, TValue>(
collection: Iterable<[TKey, TValue]>|Iterator<[TKey, TValue]>,
): Iterable<TKey>
import { single } from 'itertools-ts';
const dict = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (const key of single.keys(dict)) {
console.log(key);
}
// 'a', 'b', 'c'
Iterate up to a limit.
Stops even if more data available if limit reached.
function* limit<T>(data: Iterable<T>|Iterator<T>, count: number): Iterable<T>
import { single } from 'itertools-ts';
const matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections'];
const limit = 1;
for (const goodMovie of single.limit(matrixMovies, limit)) {
console.log(goodMovie);
}
// 'The Matrix' (and nothing else)
Map a function onto each element.
function* map<TInput, TOutput>(
data: Iterable<TInput>|Iterator<TInput>,
mapper: (datum: TInput) => TOutput,
): Iterable<TOutput>
import { single } from 'itertools-ts';
const grades = [100, 99, 95, 98, 100];
const strictParentsOpinion = (g) => (g === 100) ? 'A' : 'F';
for (const actualGrade of single.map(grades, strictParentsOpinion)) {
console.log(actualGrade);
}
// A, F, F, F, A
Returns successive overlapping pairs.
Returns empty generator if given collection contains fewer than 2 elements.
function* pairwise<T>(data: Iterable<T>|Iterator<T>): Iterable<Pair<T>>
import { single } from 'itertools-ts';
const friends = ['Ross', 'Rachel', 'Chandler', 'Monica', 'Joey', 'Phoebe'];
for (const [leftFriend, rightFriend] of single.pairwise(friends)) {
console.log(`${leftFriend} and ${rightFriend}`);
}
// Ross and Rachel, Rachel and Chandler, Chandler and Monica, ...
Repeat an item.
function* repeat<T>(item: T, repetitions: number): Iterable<T>
import { single } from 'itertools-ts';
data = 'Beetlejuice';
repetitions = 3;
for (const repeated of single.repeat(data, repetitions)) {
console.log(repeated);
}
// 'Beetlejuice', 'Beetlejuice', 'Beetlejuice'
Skip n elements in the iterable after optional offset offset.
function* skip<T>(
data: Iterable<T> | Iterator<T>,
count: number,
offset: number = 0
): Iterable<T>
import { single } from 'itertools-ts';
const movies = [
'The Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith',
'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi',
'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'
];
const prequelsRemoved = [];
for (const nonPrequel of Single.skip(movies, 3)) {
prequelsRemoved.push(nonPrequel);
} // Episodes IV - IX
const onlyTheBest = [];
for (const nonSequel of Single.skip(prequelsRemoved, 3, 3)) {
onlyTheBest.push(nonSequel);
}
// 'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi'
Extract a slice of the iterable.
function* slice<T>(
data: Iterable<T>|Iterator<T>,
start: number = 0,
count?: number,
step: number = 1,
): Iterable<T>
import { single } from 'itertools-ts';
const olympics = [1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2018, 2020, 2022];
const winterOlympics = [];
for (const winterYear of single.slice(olympics, 1, 8, 2)) {
winterOlympics.push(winterYear);
}
// [1994, 1998, 2002, 2006, 2010, 2014, 2018, 2022]
Iterate the collection sorted.
function* sort<T>(
data: Iterable<T> | Iterator<T>,
comparator?: Comparator<T>,
): Iterable<T>
Uses default sorting if optional comparator function not provided.
import { single } from 'itertools-ts';
const data = [3, 4, 5, 9, 8, 7, 1, 6, 2];
for (const datum of single.sort(data)) {
console.log(datum);
}
// 1, 2, 3, 4, 5, 6, 7, 8, 9
Return elements from the iterable as long as the predicate is true.
Stops iteration as soon as the predicate returns false, even if other elements later on would eventually return true (different from filterTrue).
function* takeWhile<T>(
data: Iterable<T> | Iterator<T>,
predicate: (item: T) => boolean
): Iterable<T>
import { single } from 'itertools-ts';
const prices = [0, 0, 5, 10, 0, 0, 9];
const isFree = (price) => price == 0;
for (const freePrice of single.takeWhile(prices, isFree)) {
console.log(freePrice);
}
// 0, 0
Iterate values of key-value pairs.
function* values<TKey, TValue>(
collection: Iterable<[TKey, TValue]>|Iterator<[TKey, TValue]>,
): Iterable<TValue>
import { single } from 'itertools-ts';
const dict = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (const value of single.keys(dict)) {
console.log(value);
}
// 1, 2, 3
Count sequentially forever.
function* count(start: number = 1, step: number = 1): Iterable<number>
import { infinite } from 'itertools-ts';
for (const i of infinite.count()) {
console.log(i);
}
// 1, 2, 3, 4, 5, ...
Cycle through the elements of a collection sequentially forever.
function* cycle<T>(iterable: Iterable<T> | Iterator<T>): Iterable<T>
import { infinite } from 'itertools-ts';
for (const item of infinite.cycle(['rock', 'paper', 'scissors'])) {
console.log(item);
}
// 'rock', 'paper', 'scissors', 'rock', 'paper', 'scissors', 'rock', ...
Repeat an item forever.
function* repeat<T>(item: T): Iterable<T>
import { infinite } from 'itertools-ts';
for (const item of infinite.repeat('bla')) {
console.log(item);
}
// bla, bla, bla, bla, bla, ...
Accumulate the running average over a list of numbers.
function* runningAverage<T>(
numbers: Iterable<T> | Iterator<T>,
initialValue?: number
): Iterable<number>
import { math } from 'itertools-ts';
const grades = [100, 80, 80, 90, 85];
for (const runningAverage of math.runningAverage(grades)) {
console.log(runningAverage);
}
// 100, 90, 86.667, 87.5, 87
Accumulate the running difference over a list of numbers.
function* runningDifference<T>(
numbers: Iterable<T> | Iterator<T>,
initialValue?: number
): Iterable<number>
import { math } from 'itertools-ts';
const credits = [1, 2, 3, 4, 5];
for (const runningDifference of math.runningDifference(credits)) {
console.log(runningDifference);
}
// -1, -3, -6, -10, -15
Provide an optional initial value to lead off the running difference.
import { math } from 'itertools-ts';
const dartsScores = [50, 50, 25, 50];
const startingScore = 501;
for (const runningScore of math.runningDifference(dartsScores, startingScore)) {
console.log(runningScore);
}
// 501, 451, 401, 376, 326
Accumulate the running maximum over a list of numbers.
function* runningMax<T>(
numbers: Iterable<T> | Iterator<T>,
initialValue?: number
): Iterable<number>
import { math } from 'itertools-ts';
const numbers = [1, 2, 1, 3, 5];
for (const runningMax of math.runningMax(numbers)) {
console.log(runningMax);
}
// 1, 2, 2, 3, 5
Accumulate the running minimum over a list of numbers.
function* runningMin<T>(
numbers: Iterable<T> | Iterator<T>,
initialValue?: number
): Iterable<number>
import { math } from 'itertools-ts';
const numbers = [3, 4, 2, 5, 1];
for (const runningMin of math.runningMin(numbers)) {
console.log(runningMin);
}
// 3, 3, 2, 2, 1
Accumulate the running product over a list of numbers.
function* runningProduct<T>(
numbers: Iterable<T> | Iterator<T>,
initialValue?: number
): Iterable<number>
import { math } from 'itertools-ts';
const numbers = [1, 2, 3, 4, 5];
for (const runningProduct of math.runningProduct(numbers)) {
console.log(runningProduct);
}
// 1, 2, 6, 24, 120
Provide an optional initial value to lead off the running product.
import { math } from 'itertools-ts';
const numbers = [1, 2, 3, 4, 5];
const initialValue = 5;
for (const runningProduct of math.runningProduct(numbers, initialValue)) {
console.log(runningProduct);
}
// 5, 5, 10, 30, 120, 600
Accumulate the running total over a list of numbers.
function* runningTotal<T>(
numbers: Iterable<T> | Iterator<T>,
initialValue?: number
): Iterable<number>
import { math } from 'itertools-ts';
const prices = [1, 2, 3, 4, 5];
for (const runningTotal of math.runningTotal(prices)) {
console.log(runningTotal);
}
// 1, 3, 6, 10, 15
Provide an optional initial value to lead off the running total.
import { math } from 'itertools-ts';
const prices = [1, 2, 3, 4, 5];
const initialValue = 5;
for (const runningTotal of math.runningTotal(prices, initialValue)) {
console.log(runningTotal);
}
// 5, 6, 8, 11, 15, 20
Reduces to the mean average.
Returns undefined
if collection is empty.
function toAverage(
data: Iterable<number> | Iterator<number>,
): number | undefined
import { reduce } from 'itertools-ts';
const grades = [100, 90, 95, 85, 94];
const finalGrade = reduce.toAverage(numbers);
// 92.8
Reduces iterable to its length.
function toCount(data: Iterable<unknown>|Iterator<unknown>): number
import { reduce } from 'itertools-ts';
const data = [1, 2, 3];
const length = reduce.toCount(data);
// 3
Reduces iterable to its first element.
function toFirst<T>(data: Iterable<T> | Iterator<T>): T
Throws LengthException
if collection is empty.
import { reduce } from 'itertools-ts';
const medals = ['gold', 'silver', 'bronze'];
const first = reduce.toFirst(medals);
// gold
Reduces iterable to its first and last elements.
function toFirstAndLast<T>(data: Iterable<T> | Iterator<T>): [T, T]
Throws LengthException
if collection is empty.
import { reduce } from 'itertools-ts';
const medals = ['gold', 'silver', 'bronze'];
const result = reduce.toFirstAndLast(medals);
// [gold, bronze]
Reduces iterable to its last element.
function toLast<T>(data: Iterable<T> | Iterator<T>): T
Throws LengthException
if collection is empty.
import { reduce } from 'itertools-ts';
const medals = ['gold', 'silver', 'bronze'];
const first = reduce.toFirst(medals);
// bronze
Reduces to the max value.
function toMax<TValue>(
data: Iterable<TValue>|Iterator<TValue>,
compareBy?: (datum: TValue) => Comparable,
): TValue|undefined
- Optional callable param
compareBy
must return comparable value. - If
compareBy
is not provided then items of given collection must be comparable. - Returns
undefined
if collection is empty.
import { reduce } from 'itertools-ts';
const numbers = [5, 3, 1, 2, 4];
const result = reduce.toMax(numbers);
// 1
const movieRatings = [
{
title: 'The Matrix',
rating: 4.7,
},
{
title: 'The Matrix Reloaded',
rating: 4.3,
},
{
title: 'The Matrix Revolutions',
rating: 3.9,
},
{
title: 'The Matrix Resurrections',
rating: 2.5,
},
];
const compareBy = (movie) => movie.rating;
const lowestRatedMovie = reduce.toMin(movieRatings, compareBy);
// {
// title: 'The Matrix',
// rating: 4.7,
// }
Reduces to the min value.
function toMin<TValue>(
data: Iterable<TValue>|Iterator<TValue>,
compareBy?: (datum: TValue) => Comparable,
): TValue|undefined
- Optional callable param
compareBy
must return comparable value. - If
compareBy
is not provided then items of given collection must be comparable. - Returns
undefined
if collection is empty.
import { reduce } from 'itertools-ts';
const numbers = [5, 3, 1, 2, 4];
const result = reduce.toMin(numbers);
// 1
const movieRatings = [
{
title: 'The Matrix',
rating: 4.7,
},
{
title: 'The Matrix Reloaded',
rating: 4.3,
},
{
title: 'The Matrix Revolutions',
rating: 3.9,
},
{
title: 'The Matrix Resurrections',
rating: 2.5,
},
];
const compareBy = (movie) => movie.rating;
const lowestRatedMovie = reduce.toMin(movieRatings, compareBy);
// {
// title: 'The Matrix Resurrections',
// rating: 2.5,
// }
Reduces collection to its lower and upper bounds.
function toMinMax<T>(
data: Iterable<T> | Iterator<T>,
compareBy?: (item: T) => Comparable
): [T?, T?]
- Optional callable param
compareBy
must return comparable value. - If
compareBy
is not provided then items of given collection must be comparable. - Returns
[undefined, undefined]
if collection is empty.
import { reduce } from 'itertools-ts';
const numbers = [5, 3, 1, 2, 4];
const result = reduce.toMinMax(numbers);
// [1, 5]
const movieRatings = [
{
title: 'The Matrix',
rating: 4.7,
},
{
title: 'The Matrix Reloaded',
rating: 4.3,
},
{
title: 'The Matrix Revolutions',
rating: 3.9,
},
{
title: 'The Matrix Resurrections',
rating: 2.5,
},
];
const compareBy = (movie) => movie.rating;
const lowestRatedMovie = reduce.toMin(movieRatings, compareBy);
// [{
// title: 'The Matrix Resurrections',
// rating: 2.5,
// },
// {
// title: 'The Matrix',
// rating: 4.7,
// }]
Reduces to the product of its elements.
Returns undefined
if collection is empty.
function toProduct(data: Iterable<number>|Iterator<number>): number|undefined
import { reduce } from 'itertools-ts';
const primeFactors = [5, 2, 2];
const number = reduce.toProduct(primeFactors);
// 20
Reduces given collection to its range (difference between max and min).
function toRange(numbers: Iterable<number|string> | Iterator<number|string>): number
Returns 0
if iterable source is empty.
import { reduce } from 'itertools-ts';
const grades = [100, 90, 80, 85, 95];
const range = reduce.toRange(numbers);
// 20
Reduces to the sum of its elements.
function toSum(data: Iterable<number>|Iterator<number>): number
import { reduce } from 'itertools-ts';
const parts = [10, 20, 30];
const sum = reduce.toSum(parts);
// 60
Reduce elements to a single value using reducer function.
function toValue<TInput, TOutput>(
data: Iterable<TInput>|Iterator<TInput>,
reducer: (carry: TOutput|undefined, datum: TInput) => TOutput,
initialValue?: TOutput,
): TOutput|undefined
import { reduce } from 'itertools-ts';
const input = [1, 2, 3, 4, 5];
const sum = (carry, item) => carry + item;
const result = reduce.toValue(input, sum, 0);
// 15
Iterates cartesian product of given iterables.
function* cartesianProduct<T extends Array<Iterable<unknown> | Iterator<unknown>>>(
...iterables: T
): Iterable<ZipTuple<T, never>>
import { set } from 'itertools-ts';
const numbers = [1, 2];
const letters = ['a', 'b'];
const chars = ['!', '?'];
for (const tuple of set.cartesianProduct(numbers, letters, chars)) {
console.log(tuple);
}
/*
[1, 'a', '!'],
[1, 'a', '?'],
[1, 'b', '!'],
[1, 'b', '?'],
[2, 'a', '!'],
[2, 'a', '?'],
[2, 'b', '!'],
[2, 'b', '?'],
*/
Filter out elements from the iterable only returning distinct elements.
function* distinct<T>(
data: Iterable<T>|Iterator<T>,
compareBy?: (datum: T) => Comparable
): Iterable<T>
Always treats different instances of objects and arrays as unequal.
import { set } from 'itertools-ts';
const chessSet = ['rook', 'rook', 'knight', 'knight', 'bishop', 'bishop', 'king', 'queen', 'pawn', 'pawn'];
for (const chessPiece of set.distinct(chessSet)) {
console.log(chessPiece);
}
// rook, knight, bishop, king, queen, pawn
const users = [
{ 'name': 'John', 'id': 1 },
{ 'name': 'Mary', 'id': 2 },
{ 'name': 'Mary', 'id': 3 },
{ 'name': 'John', 'id': 4 },
{ 'name': 'Jane', 'id': 5 },
];
for (const user of set.distinct(users, (item) => item['name'])) {
console.log(user);
}
// { 'name': 'John', 'id': 1 }, { 'name': 'Mary', 'id': 2 }, { 'name': 'Jane', 'id': 5 }
Iterates intersection of iterables.
function* intersection<T>(...iterables: Array<Iterable<T> | Iterator<T>>): Iterable<T>
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset intersection rules apply.
import { set } from 'itertools-ts';
const chessPieces = ['rook', 'knight', 'bishop', 'queen', 'king', 'pawn'];
const shogiPieces = ['rook', 'knight', 'bishop', 'king', 'pawn', 'lance', 'gold general', 'silver general'];
for (const commonPiece of set.intersection(chessPieces, shogiPieces)) {
console.log(commonPiece);
}
// rook, knight, bishop, king, pawn
Iterates M-partial intersection of iterables.
function* partialIntersection<T>(
minIntersectionCount: number,
...iterables: Array<Iterable<T> | Iterator<T>>
): Iterable<T>
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset intersection rules apply.
import { set } from 'itertools-ts';
const staticallyTyped = ['c++', 'java', 'c#', 'go', 'haskell'];
const dynamicallyTyped = ['php', 'python', 'javascript', 'typescript'];
const supportsInterfaces = ['php', 'java', 'c#', 'typescript'];
for (const language of set.partialIntersection(2, staticallyTyped, dynamicallyTyped, supportsInterfaces)) {
console.log(language);
}
// c++, java, c#, go, php
Iterates the symmetric difference of iterables.
function* symmetricDifference<T>(
...iterables: Array<Iterable<T> | Iterator<T>>
): Iterable<T>
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset difference rules apply.
import { set } from 'itertools-ts';
const a = [2, 3, 4, 7];
const b = [2, 3, 5, 8];
const c = [2, 3, 6, 9];
for (const item of set.symmetricDifference(a, b, c)) {
console.log(item);
}
// 4, 5, 6, 7, 8, 9
Iterates the union of iterables.
function* union<T>(...iterables: Array<Iterable<T> | Iterator<T>>): Iterable<T>
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset difference rules apply.
import { set } from 'itertools-ts';
const a = [1, 2, 3];
const b = [2, 3, 4];
const c = [3, 4, 5];
for (const item of set.symmetricDifference(a, b, c)) {
console.log(item);
}
// 1, 2, 3, 4, 5
Returns true if all elements match the predicate function.
function allMatch<T>(
data: Iterable<T> | Iterator<T>,
predicate: (item: T) => boolean
): boolean
Empty collections return true.
import { summary } from "itertools-ts";
const finalFantasyNumbers = [4, 5, 6];
const isOnSuperNintendo = (ff) => ff >= 4 && ff <= 6;
const trueResult = summary.allMatch(finalFantasyNumbers, isOnSuperNintendo);
// true
const isOnPlaystation = (ff) => ff >= 7 && ff <= 9;
const falseResult = summary.allMatch(finalFantasyNumbers, isOnPlaystation);
// false
Return true if all elements in given collection are unique.
function allUnique(data: Iterable<unknown> | Iterator<unknown>): boolean
Empty collections return true.
Considers different instances of data containers to be different, even if they have the same content.
import { summary } from "itertools-ts";
const uniqueNumbers = [1, 2, 3, 4, 5];
summary.allUnique(uniqueNumbers);
// true
const notUniqueNumbers = [1, 1, 2, 2, 3];
summary.allUnique(notUniqueNumbers);
// false
Returns true if any element matches the predicate function.
function anyMatch<T>(
data: Iterable<T> | Iterator<T>,
predicate: (item: T) => boolean
): boolean
Empty collections return false.
import { summary } from "itertools-ts";
const answers = ['fish', 'towel', 42, "don't panic"];
const isUltimateAnswer = (a) => a == 42;
const trueResult = summary.anyMatch(answers, isUltimateAnswer);
// true
Returns true if exactly n items are true according to a predicate function.
- Predicate is optional.
- Default predicate is boolean value of each item.
function exactlyN<T>(
data: Iterable<T> | Iterator<T>,
n: number,
predicate?: (item: T) => boolean,
): boolean
import { summary } from "itertools-ts";
const twoTruthsAndALie = [true, true, false];
const n = 2;
const trueResult = summary.exactlyN(twoTruthsAndALie, n);
// true
const ages = [18, 21, 24, 54];
const m = 4;
const predicate = (age) => age >= 21;
const falseResult = Summary::exactlyN(ages, m, predicate);
// false
Returns true if given data is an AsyncIterable
instance.
function isAsyncIterable(input: unknown): boolean
import { summary } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
summary.isIterable(input); // false
summary.isIterable(input[Symbol.asyncIterator]()) // false
summary.isIterable(1); // false
Returns true if given data is an Iterable
instance.
function isIterable(input: unknown): boolean
import { summary } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
summary.isIterable(input); // true
summary.isIterable(input[Symbol.iterator]()) // false
summary.isIterable(1); // false
Returns true if given data is an Iterator
instance.
function isIterator(input: unknown): boolean
import { summary } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
summary.isIterator(input[Symbol.iterator]()) // true
summary.isIterator(input); // false
summary.isIterator(1); // false
Returns true if elements are reverse sorted, otherwise false.
function isReversed(data: Iterable<Comparable> | Iterator<Comparable>): boolean
- Elements must be comparable.
- Returns true if empty or has only one element.
import { summary } from "itertools-ts";
const reversedNumbers = [5, 4, 3, 2, 1];
Summary.isReversed(reversedNumbers);
// true
const numbers = [1, 4, 3, 2, 1];
Summary.isReversed(numbers);
// false
Returns true if elements are sorted, otherwise false.
function isSorted(data: Iterable<Comparable> | Iterator<Comparable>): boolean
- Elements must be comparable.
- Returns true if empty or has only one element.
import { summary } from "itertools-ts";
const sortedNumbers = [1, 2, 3, 4, 5];
Summary.isSorted(sortedNumbers);
// true
const numbers = [3, 2, 3, 4, 5];
Summary.isSorted(numbers);
// false
Returns true if given data is a string.
function isString(input: unknown): boolean
import { summary } from "itertools-ts";
summary.isString('') // true
summary.isString('abc') // true
summary.isString(String('abc')) // true
summary.isString(1); // false
Returns true if no element matches the predicate function.
function noneMatch<T>(
data: Iterable<T> | Iterator<T>,
predicate: (item: T) => boolean
): boolean
Empty collections return true.
import { summary } from "itertools-ts";
const grades = [45, 50, 61, 0];
const isPassingGrade = (grade) => grade >= 70;
const trueResult = summary.noneMatch(grades, isPassingGrade);
// true
Returns true if all given collections are the same.
For single collection or empty collections list returns true.
function same(...collections: Array<Iterable<unknown> | Iterator<unknown>>): boolean
import { summary } from "itertools-ts";
const cocaColaIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid'];
const pepsiIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid'];
const spriteIngredients = ['carbonated water', 'sugar', 'citric acid', 'lemon lime flavorings'];
const trueResult = summary.same(cocaColaIngredients, pepsiIngredients);
// true
const falseResult = summary.same(cocaColaIngredients, spriteIngredients);
// false
Returns true if all given collections have the same lengths.
For single collection or empty collections list returns true.
function same(
...collections: Array<Iterable<unknown> | Iterator<unknown>>
): boolean
import { summary } from "itertools-ts";
const prequels = ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith'];
const originals = ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi'];
const sequels = ['The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'];
const trueResult = summary.sameCount(prequels, originals, sequels);
// true
const batmanMovies = ['Batman Begins', 'The Dark Knight', 'The Dark Knight Rises'];
const matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections'];
const falseResult = summary.sameCount(batmanMovies, matrixMovies);
// false
Return several independent (duplicated) iterators from a single iterable.
function tee<T>(
collection: Iterable<T> | Iterator<T>,
count: number
): Array<RelatedIterable<T>>
Once tee has been called to duplicate iterators, it is advisable to not use the original input iterator any further.
Duplicating iterators can use up memory. Consider if tee is the right solution. For example, arrays and most iterators can be rewound and reiterated without need for duplication.
import { transform } from "itertools-ts";
const daysOfWeek = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'];
const count = 3;
const [week1, week2, week3] = transform.tee(data, count);
// Each week contains iterator containing ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
Returns Array
instance of given collection or iterator.
function toArray<T>(
collection: Iterable<T>|Iterator<T>
): Array<T>
import { transform } from "itertools-ts";
const iterator = transform.toIterator([1, 2, 3, 4, 5]);
const result = transform.toArray(iterator);
// [1, 2, 3, 4, 5]
Returns AsyncIterable
instance of given collection, record or iterator (sync or async).
Throws InvalidArgumentError
if given data is not a collection or an iterator.
function toAsyncIterable<T>(
collection:
| Iterable<T>
| Iterator<T>
| AsyncIterable<T>
| AsyncIterator<T>
| Record<RecordKey, unknown>
): AsyncIterable<T>
import { transform } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = transform.toAsyncIterable(input);
// AsyncIterable<[1, 2, 3, 4, 5]>
Returns AsyncIterator
instance of given collection or iterator.
Throws InvalidArgumentError
if given data is not a collection or an iterator.
function toAsyncIterator<T>(
collection: Iterable<T> | Iterator<T> | AsyncIterable<T> | AsyncIterator<T>
): AsyncIterator<T>
import { transform } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = transform.toAsyncIterator(input);
console.log(result.next !== undefined);
// true
Returns Iterable
instance of given collection, record or iterator.
Throws InvalidArgumentError
if given data is not a collection or an iterator.
function toIterable<T>(
collection: Iterable<T>|Iterator<T>|Record<string|number|symbol, unknown>
): Iterable<T>
import { transform } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = transform.toIterable(input);
// [1, 2, 3, 4, 5]
Returns Iterator
instance of given collection or iterator.
Throws InvalidArgumentError
if given data is not a collection or an iterator.
function toIterator<T>(collection: Iterable<T>|Iterator<T>): Iterator<T>
import { transform } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = transform.toIterator(input);
console.log(result.next !== undefined);
// true
Converts given iterable of key-value pairs to Map.
function toMap<TKey, TValue>(
pairs: Iterable<[TKey, TValue]> | Iterator<[TKey, TValue]> | Record<string|number|symbol, unknown>
): Map<TKey, TValue>
import { transform } from "itertools-ts";
const input = [['a', 1], ['b', 2], ['c', 3]];
const result = transform.toMap(input);
// Map([['a', 1], ['b', 2], ['c', 3]])
Converts given iterable to Set.
function toSet<T>(
collection: Iterable<T> | Iterator<T>
): Set<T>
import { transform } from "itertools-ts";
const input = [1, 1, 2, 2, 3, 3];
const result = transform.toSet(input);
// Set([1, 2, 3])
Streams provide a fluent interface to transform arrays and iterables (sync or async) through a pipeline of operations.
Streams are made up of:
- One stream source factory method to create the stream.
- Zero or more stream operators that transform the stream to a new stream.
- Terminal operation of either:
- Stream terminal operation to transform the stream to a value or data structure.
const result1 = Stream.of([1, 1, 2, 2, 3, 4, 5]) .distinct() // [1, 2, 3, 4, 5] .map((x) => x**2) // [1, 4, 9, 16, 25] .filter((x) => x < 10) // [1, 4, 9] .toSum(); // 14 // Async example const result2 = await AsyncStream.of([1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x))) .distinct() // [1, 2, 3, 4, 5] .map((x) => x**2) // [1, 4, 9, 16, 25] .filter((x) => x < 10) // [1, 4, 9] .toSum(); // 14
- The stream is iterated via a
for
loop.const result1 = Stream.of([1, 1, 2, 2, 3, 4, 5]) .distinct() // [1, 2, 3, 4, 5] .map((x) => x**2) // [1, 4, 9, 16, 25] .filter((x) => x < 10); // [1, 4, 9] for (const item of result1) { // 1, 4, 9 } // Async example const result2 = AsyncStream.of([1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x))) .distinct() // [1, 2, 3, 4, 5] .map((x) => x**2) // [1, 4, 9, 16, 25] .filter((x) => x < 10); // [1, 4, 9] for await (const item of result2) { // 1, 4, 9 }
- Stream terminal operation to transform the stream to a value or data structure.
Creates stream from an iterable.
Stream.of(data: Iterable<unknown>|Iterator<unknown>): Stream
import { Stream } from "itertools-ts";
const iterable = [1, 2, 3];
const result = Stream.of(iterable)
.chainWith([4, 5, 6], [7, 8, 9])
.zipEqualWith([1, 2, 3, 4, 5, 6, 7, 8, 9])
.toArray();
// [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9]]
Creates stream of nothing.
Stream.ofEmpty(): Stream
import { Stream } from "itertools-ts";
const result = Stream.ofEmpty()
.chainWith([1, 2, 3])
.toArray();
// [1, 2, 3]
Create an infinite count stream.
Stream.ofCount(start: number = 1, step: number = 1): Stream
import { Stream } from "itertools-ts";
const result = Stream.ofCount(0, 10)
.limit(5)
.toArray();
// [0, 10, 20, 30, 40]
Create an infinite cycle stream.
Stream.ofCycle(iterable: Iterable<unknown> | Iterator<unknown>): Stream
import { Stream } from "itertools-ts";
const result = Stream.ofCycle([1, 2, 3])
.limit(7)
.toArray();
// [1, 2, 3, 1, 2, 3, 1]
Create an infinite stream repeating given item.
Stream.ofRepeat(item: unknown): Stream
import { Stream } from "itertools-ts";
const result = Stream.ofRepeat('bla')
.limit(5)
.toArray();
// [bla, bla, bla, bla, bla]
Iterate cartesian product of iterable source with another iterable collections.
stream.cartesianProductWith(
...iterables: Array<Iterable<unknown> | Iterator<unknown>>
): Stream
import { Stream } from "itertools-ts";
const numbers = [1, 2];
const result = Stream.of(numbers)
.cartesianProductWith(['a', 'b'], ['!', '?'])
.toArray();
/*
[
[1, 'a', '!'],
[1, 'a', '?'],
[1, 'b', '!'],
[1, 'b', '?'],
[2, 'a', '!'],
[2, 'a', '?'],
[2, 'b', '!'],
[2, 'b', '?'],
]
*/
Return a stream chaining additional sources together into a single consecutive stream.
stream.chainWith(
...iterables: Array<Iterable<unknown>|Iterator<unknown>>
): Stream
import { Stream } from "itertools-ts";
const input = [1, 2, 3];
const result = Stream.of(input)
.chainWith([4, 5, 6])
.chainWith([7, 8, 9])
.toArray();
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
Return a stream consisting of chunks of elements from the stream.
stream.chunkwise(chunkSize: number): Stream
Chunk size must be at least 1.
import { Stream } from "itertools-ts";
const friends = ['Ross', 'Rachel', 'Chandler', 'Monica', 'Joey'];
const result = Stream.of(friends)
.chunkwise(2)
.toArray();
// [['Ross', 'Rachel'], ['Chandler', 'Monica'], ['Joey']]
Return a stream consisting of overlapping chunks of elements from the stream.
stream.chunkwiseOverlap(
chunkSize: number,
overlapSize: number,
includeIncompleteTail: boolean = true,
): Stream
- Chunk size must be at least 1.
- Overlap size must be less than chunk size.
import { Stream } from "itertools-ts";
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = Stream.of(numbers)
.chunkwiseOverlap(3, 1)
.toArray()
// [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]]
Compress to a new stream by filtering out data that is not selected.
stream.compress(selectors: Iterable<number|boolean> | Iterator<number|boolean>): Stream
Selectors indicate which data. True value selects item. False value filters out data.
import { Stream } from "itertools-ts";
const input = [1, 2, 3];
const result = Stream.of(input)
.compress([0, 1, 1])
.toArray();
// [2, 3]
Return a stream filtering out elements from the stream only returning distinct elements.
stream.distinct(compareBy?: (datum: unknown) => Comparable): Stream
import { Stream } from "itertools-ts";
const input = [1, 2, 1, 2, 3, 3, '1', '1', '2', '3'];
const numbers = Stream.of(input)
.distinct()
.toArray();
// [1, 2, 3, '1', '2', '3']
const users = [
{ 'name': 'John', 'id': 1 },
{ 'name': 'Mary', 'id': 2 },
{ 'name': 'Mary', 'id': 3 },
{ 'name': 'John', 'id': 4 },
{ 'name': 'Jane', 'id': 5 },
];
const result = Stream.of(input)
.distinct((item) => item['name'])
.toArray();
/*
[
{ 'name': 'John', 'id': 1 },
{ 'name': 'Mary', 'id': 2 },
{ 'name': 'Jane', 'id': 5 },
]
*/
Drop elements from the stream while the predicate function is true.
stream.dropWhile(predicate: (item: unknown) => boolean): Stream
Once the predicate function returns false once, all remaining elements are returned.
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5]
const result = Stream.of(input)
.dropWhile((value) => value < 3)
.toArray();
// [3, 4, 5]
Enumerates elements of the stream.
stream.enumerate(): Stream
import { Stream } from "itertools-ts";
const input = ['a', 'b', 'c', 'd', 'e'];
const stream = Stream.of(input)
.enumerate()
.toArray();
// [[0, 'a'], [1, 'b'], [2, 'c'], [3, 'd'], [4, 'e']]
Filter out elements from the stream only keeping elements where there predicate function is true.
stream.filter(predicate: (item: unknown) => boolean): Stream
import { Stream } from "itertools-ts";
const input = [1, -1, 2, -2, 3, -3];
const result = Stream.of(input)
.filter((value) => value > 0)
.toArray();
// [1, 2, 3]
Map a function onto the elements of the stream and flatten the results.
stream.flatMap(mapper: (datum: unknown) => unknown): Stream
import { Stream } from "itertools-ts";
const data = [1, 2, 3, 4, 5];
const mapper = (item) => (item % 2 === 0) ? [item, item] : item;
const result = Stream.of(data)
.flatMap(mapper)
.toArray();
// [1, 2, 2, 3, 4, 4, 5]
Flatten a multidimensional stream.
stream.flatten(dimensions: number = Infinity): Stream
import { Stream } from "itertools-ts";
const data = [1, [2, 3], [4, 5]];
const result = Stream.of(data)
.flatten()
.toArray();
// [1, 2, 3, 4, 5]
Return a stream intersecting the stream with the input iterables.
stream.intersectionWith(...iterables: Array<Iterable<unknown> | Iterator<unknown>>): Stream
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset intersection rules apply.
import { Stream } from 'itertools-ts';
const chessPieces = ['rook', 'knight', 'bishop', 'queen', 'king', 'pawn'];
const shogiPieces = ['rook', 'knight', 'bishop', 'king', 'pawn', 'lance', 'gold general', 'silver general'];
const result = Stream.of(chessPieces)
.intersectionWith(shogiPieces)
.toArray();
// [rook, knight, bishop, king, pawn]
Group stream data by a common data element.
Iterate pairs of group name and collection of grouped items.
stream.groupBy(
groupKeyFunction: (item: unknown) => string,
itemKeyFunction?: (item: unknown) => string,
): Stream
- The
groupKeyFunction
determines the key to group elements by. - The optional
itemKeyFunction
allows custom indexes within each group member. - Collection of grouped items may be an array or an object (depends on presence of
itemKeyFunction
param).
import { Stream } from 'itertools-ts';
const cartoonCharacters = [
['Garfield', 'cat'],
['Tom', 'cat'],
['Felix', 'cat'],
['Heathcliff', 'cat'],
['Snoopy', 'dog'],
['Scooby-Doo', 'dog'],
['Odie', 'dog'],
['Donald', 'duck'],
['Daffy', 'duck'],
];
const result = Stream.of(cartoonCharacters)
.groupBy((x) => x[1])
.toArray();
/*
[
['cat', [
['Garfield', 'cat'],
['Tom', 'cat'],
['Felix', 'cat'],
['Heathcliff', 'cat'],
]],
['dog', [
['Snoopy', 'dog'],
['Scooby-Doo', 'dog'],
['Odie', 'dog'],
]],
['duck', [
['Donald', 'duck'],
['Daffy', 'duck'],
]],
]
*/
Iterate keys of key-value pairs.
stream.keys(): Stream
import { Stream } from 'itertools-ts';
const dict = new Map([['a', 1], ['b', 2], ['c', 3]]);
const result = Stream.of(dict)
.keys()
.toArray();
// ['a', 'b', 'c']
Return a stream up to a limit.
Stops even if more data available if limit reached.
stream.limit(count: number): Stream
import { Stream } from "itertools-ts";
const matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections'];
const limit = 1;
const goodMovies = Stream.of(matrixMovies)
.limit(limit)
.toArray();
// ['The Matrix'] (and nothing else)
Return a stream containing the result of mapping a function onto each element of the stream.
stream.map(mapper: (datum: unknown) => unknown): Stream
import { Stream } from "itertools-ts";
const grades = [100, 95, 98, 89, 100];
const result = Stream.of(grades)
.map((grade) => grade === 100 ? 'A' : 'F')
.toArray();
// [A, F, F, F, A]
Return a stream consisting of pairs of elements from the stream.
stream.pairwise(): Stream
Returns empty stream if given collection contains less than 2 elements.
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const stream = Stream.of(input)
.pairwise()
.toArray();
// [[1, 2], [2, 3], [3, 4], [4, 5]]
Return a stream partially intersecting the stream with the input iterables.
stream.partialIntersectionWith(
minIntersectionCount: number,
...iterables: Array<Iterable<unknown> | Iterator<unknown>>
): Stream
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset intersection rules apply.
import { Stream } from 'itertools-ts';
const staticallyTyped = ['c++', 'java', 'c#', 'go', 'haskell'];
const dynamicallyTyped = ['php', 'python', 'javascript', 'typescript'];
const supportsInterfaces = ['php', 'java', 'c#', 'typescript'];
const result = Stream.of(staticallyTyped)
.partialIntersectionWith(2, dynamicallyTyped, supportsInterfaces)
.toArray();
// ['c++', 'java', 'c#', 'go', 'php']
Return a stream accumulating the running average (mean) over the stream.
stream.runningAverage(initialValue?: number): Stream
import { Stream } from 'itertools-ts';
const input = [1, 3, 5];
const result = Stream.of(input)
.runningAverage()
.toArray();
// [1, 2, 3]
Return a stream accumulating the running difference over the stream.
stream.runningDifference(initialValue?: number): Stream
import { Stream } from 'itertools-ts';
const input = [1, 2, 3, 4, 5];
const result = Stream.of(input)
.runningDifference()
.toArray();
// [-1, -3, -6, -10, -15]
Return a stream accumulating the running max over the stream.
stream.runningMax(initialValue?: number): Stream
import { Stream } from 'itertools-ts';
const input = [1, -1, 2, -2, 3, -3];
const result = Stream.of(input)
.runningMax()
.toArray();
// [1, 1, 2, 2, 3, 3]
Return a stream accumulating the running min over the stream.
stream.runningMin(initialValue?: number): Stream
import { Stream } from 'itertools-ts';
const input = [1, -1, 2, -2, 3, -3];
const result = Stream.of(input)
.runningMin()
.toArray();
// [1, -1, -1, -2, -2, -3]
Return a stream accumulating the running product over the stream.
stream.runningProduct(initialValue?: number): Stream
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = Stream.of(input)
.runningProduct()
.toArray();
// [1, 2, 6, 24, 120]
Return a stream accumulating the running total over the stream.
stream.runningTotal(initialValue?: number): Stream
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = Stream.of(input)
.runningTotal()
.toArray();
// [1, 3, 6, 10, 15]
Skip some elements of the stream.
skip(count: number, offset = 0): Stream
import { Stream } from "itertools-ts";
const movies = [
'The Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith',
'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi',
'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'
];
const onlyTheBest = Stream.of(movies)
.skip(3)
.skip(3, 3)
.toArray();
// ['A New Hope', 'The Empire Strikes Back', 'Return of the Jedi']
Extract a slice of the stream.
stream.slice(start: number = 0, count?: number, step: number = 1): Stream
import { Stream } from "itertools-ts";
const olympics = [1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2018, 2020, 2022];
const summerOlympics = Stream.of(olympics)
.slice(0, 8, 2)
.toArray();
// [1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020]
Sorts the stream.
stream.sort(comparator?: Comparator<unknown>): Stream
If comparator is not provided, the elements of the iterable source must be comparable.
import { Stream } from "itertools-ts";
const input = [3, 4, 5, 9, 8, 7, 1, 6, 2];
const result = Stream.of(input)
.sort()
.toArray();
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
Return a stream of the symmetric difference of the stream and the given iterables.
stream.symmetricDifferenceWith(...iterables: Array<Iterable<unknown> | Iterator<unknown>>): Stream
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset difference rules apply.
import { Stream } from 'itertools-ts';
const a = [2, 3, 4, 7];
const b = [2, 3, 5, 8];
const c = [2, 3, 6, 9];
const result = Stream.of(a)
.symmetricDifferenceWith(b, c)
.toArray();
// [4, 5, 6, 7, 8, 9]
Keep elements from the stream as long as the predicate is true.
stream.takeWhile(predicate: (item: unknown) => boolean): Stream
import { Stream } from 'itertools-ts';
const input = [1, -1, 2, -2, 3, -3];
const result = Stream.of(input)
.takeWhile((value) => Math.abs(value) < 3)
.toArray();
// [1, -1, 2, -2]
Return a stream of union of the stream with the input iterables.
stream.unionWith(...iterables: Array<Iterable<unknown> | Iterator<unknown>>): Stream
- Always treats different instances of objects and arrays as unequal.
- If input iterables produce duplicate items, then multiset difference rules apply.
import { Stream } from 'itertools-ts';
const a = [1, 2, 3];
const b = [2, 3, 4];
const c = [3, 4, 5];
const result = Stream.of(a)
.unionWith(b, c)
.toArray();
// [1, 2, 3, 4, 5]
Iterate keys of key-value pairs.
stream.values(): Stream
import { Stream } from 'itertools-ts';
const dict = new Map([['a', 1], ['b', 2], ['c', 3]]);
const result = Stream.of(dict)
.values()
.toArray();
// [1, 2, 3]
Return a stream consisting of multiple iterable collections streamed simultaneously.
stream.zipWith(
...iterables: Array<Iterable<unknown>|Iterator<unknown>>
): Stream
For uneven lengths, iterations stops when the shortest iterable is exhausted.
import { Stream } from "itertools-ts";
const input = [1, 2, 3];
const stream = Stream.of(input)
.zipWith([4, 5, 6])
.toArray();
// [[1, 4], [2, 5], [3, 6]]
Return a stream consisting of multiple iterable collections of equal lengths streamed simultaneously.
stream.zipEqualWith(
...iterables: Array<Iterable<unknown>|Iterator<unknown>>
): Stream
Works like Stream.zipWith()
method but throws LengthException
if lengths not equal,
i.e., at least one iterator ends before the others.
import { Stream } from "itertools-ts";
const input = [1, 2, 3];
const stream = Stream.of(input)
.zipEqualWith([4, 5, 6]);
for (const zipped of stream) {
// [1, 4], [2, 5], [3, 6]
}
Return a stream consisting of multiple iterable collections streamed simultaneously.
zipFilledWith(
filler: unknown,
...iterables: Array<Iterable<unknown>|Iterator<unknown>>
): Stream
- Iteration continues until the longest iterable is exhausted.
- For uneven lengths, the exhausted iterables will produce
filler
value for the remaining iterations.
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const stream = Stream.of(input)
.zipFilledWith('filler', [4, 5, 6]);
for (const zipped of stream) {
// [1, 4], [2, 5], [3, 6], [4, 'filler'], [5, 'filler']
}
Return a stream consisting of multiple iterable collections streamed simultaneously.
stream.zipLongestWith(
...iterables: Array<Iterable<unknown>|Iterator<unknown>>
): Stream
- Iteration continues until the longest iterable is exhausted.
- For uneven lengths, the exhausted iterables will produce
undefined
for the remaining iterations.
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const stream = Stream.of(input)
.zipLongestWith([4, 5, 6]);
for (const zipped of stream) {
// [1, 4], [2, 5], [3, 6], [4, undefined], [5, undefined]
}
Return several independent (duplicated) streams.
stream.tee(count: number): Array<Stream>
import { Stream } from "itertools-ts";
const daysOfWeek = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'];
const count = 3;
const [week1Stream, week2Stream, week3Stream] = Stream.of(daysOfWeek)
.tee(count);
// Each weekStream contains ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
Returns an array of stream elements.
stream.toArray(): Array<unknown>
import { Stream } from "itertools-ts";
const result = Stream.of([1, 2, 3, 4, 5])
.map((x) => x**2)
.toArray();
// [1, 4, 9, 16, 25]
Converts stream to Map.
stream.toMap(): Map<unknown, unknown>
Stream collection must contain only key-value pairs as elements.
import { Stream } from "itertools-ts";
const result = Stream.of([1, 2, 3])
.enumerate()
.toMap();
// Map([[0, 1], [1, 2], [2, 3]])
Converts stream to Set.
stream.toSet(): Set<unknown>
import { Stream } from "itertools-ts";
const result = Stream.of([1, 1, 2, 2, 3, 3])
.toMap();
// Set([1, 2, 3])
Reduces iterable source to the mean average of its items.
stream.toAverage(): number|undefined
Returns undefined
if iterable source is empty.
import { Stream } from "itertools-ts";
const input = [2, 4, 6, 8];
const result = Stream.of(iterable)
.toAverage();
// 5
Reduces iterable source to its length.
stream.toCount(): number
import { Stream } from "itertools-ts";
const input = [10, 20, 30, 40, 50];
const result = Stream.of(iterable)
.toCount();
// 5
Reduces stream to its first element.
stream.toFirst(): unknown
Throws LengthException
if stream is empty.
import { Stream } from "itertools-ts";
const input = [10, 20, 30];
const result = Stream.of(input)
.toFirst();
// 10
Reduces stream to its first last elements.
stream.toFirstAndLast(): [unknown, unknown]
Throws LengthException
if stream is empty.
import { Stream } from "itertools-ts";
const input = [10, 20, 30];
const result = Stream.of(input)
.toFirstAndLast();
// [10, 30]
Reduces stream to its last element.
stream.toLast(): unknown
Throws LengthException
if stream is empty.
import { Stream } from "itertools-ts";
const input = [10, 20, 30];
const result = Stream.of(input)
.toLast();
// 30
Reduces stream to its max value.
stream.toMax<TComparable>(compareBy?: (datum: unknown) => TComparable): unknown|undefined
- Optional callable param
compareBy
must return comparable value. - If
compareBy
is not provided then items of given collection must be comparable. - Returns
undefined
if collection is empty.
import { Stream } from "itertools-ts";
const input = [1, -1, 2, -2, 3, -3];
const result = Stream.of(iterable)
.toMax();
// 3
Reduces stream to its min value.
stream.toMin<TComparable>(compareBy?: (datum: unknown) => TComparable): unknown|undefined
- Optional callable param
compareBy
must return comparable value. - If
compareBy
is not provided then items of given collection must be comparable. - Returns
undefined
if collection is empty.
import { Stream } from "itertools-ts";
const input = [1, -1, 2, -2, 3, -3];
const result = Stream.of(iterable)
.toMin();
// -3
Reduces stream to its min and max values.
toMinMax(compareBy?: (item: unknown) => Comparable): [unknown?, unknown?]
- Optional callable param
compareBy
must return comparable value. - If
compareBy
is not provided then items of given collection must be comparable. - Returns
[undefined, undefined]
if collection is empty.
import { Stream } from "itertools-ts";
const input = [1, -1, 2, -2, 3, -3];
const result = Stream.of(iterable)
.toMinMax();
// [-3, 3]
Reduces iterable source to the product of its items.
stream.toProduct(): number|undefined
Returns undefined
if stream is empty.
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = Stream.of(input)
.toProduct();
// 120
Reduces stream to its range (difference between max and min).
stream.toRange(): number
Returns 0
if iterable source is empty.
import { Stream } from "itertools-ts";
const grades = [100, 90, 80, 85, 95];
const range = stream.of(numbers)
.toRange();
// 20
Reduces iterable source to the sum of its items.
stream.toSum(): number
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = Stream.of(iterable)
.toSum();
// 15
Reduces iterable source like array_reduce() function.
stream.toValue<T>(
reducer: (carry: T|undefined, datum: unknown) => T,
initialValue?: T,
): T|undefined
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const result = Stream.of(input)
.toValue((carry, item) => carry + item);
// 15
Returns true if all elements of stream match the predicate function.
allMatch(predicate: (item: unknown) => boolean): boolean
For empty stream returns true.
import { Stream } from "itertools-ts";
const finalFantasyNumbers = [4, 5, 6];
const isOnSuperNintendo = (ff) => ff >= 4 && ff <= 6;
const trueResult = Stream.of(finalFantasyNumbers)
.allMatch(isOnSuperNintendo);
// true
Returns true if all elements in stream are unique.
stream.allUnique(): boolean
Empty collections return true.
Considers different instances of data containers to be different, even if they have the same content.
import { summary } from "itertools-ts";
import { Stream } from './stream';
const uniqueNumbers = [1, 2, 3, 4, 5];
Stream.of(uniqueNumbers)
.allUnique();
// true
const notUniqueNumbers = [1, 1, 2, 2, 3];
Stream.of(notUniqueNumbers)
.allUnique();
// false
Returns true if any element of stream matches the predicate function.
anyMatch(predicate: (item: unknown) => boolean): boolean
For empty stream returns false.
import { Stream } from "itertools-ts";
const answers = ['fish', 'towel', 42, "don't panic"];
const isUltimateAnswer = (a) => a == 42;
const trueResult = Stream.of(answers)
.anyMatch(answers, isUltimateAnswer);
// true
Returns true if exactly n items are true according to a predicate function.
- Predicate is optional.
- Default predicate is boolean value of each item.
stream.exactlyN(n: number, predicate?: (item: unknown) => boolean): boolean
import { Stream } from "itertools-ts";
import stream = require("node:stream");
const twoTruthsAndALie = [true, true, false];
const n = 2;
const boolean = stream.of(twoTruthsAndALie)
.exactlyN(n);
// true
Returns true if stream is sorted in reverse descending order; otherwise false.
stream.isReversed(): boolean
Items of stream must be comparable.
Returns true if iterable source is empty or has only one element.
import { Stream } from "itertools-ts";
const reversed = [5, 4, 3, 2, 1];
Stream.of(reversed)
.isReversed();
// true
const input = [1, 2, 3, 2, 1];
Stream.of(input)
.isReversed();
// false
Returns true if iterable source is sorted in ascending order; otherwise false.
stream.isSorted(): boolean
Items of iterable source must be comparable.
Returns true if iterable source is empty or has only one element.
import { Stream } from "itertools-ts";
const sorted = [1, 2, 3, 4, 5];
Stream.of(sorted)
.isSorted();
// true
const input = [1, 2, 3, 2, 1];
Stream.of(input)
.isSorted();
// false
Returns true if no element of stream matches the predicate function.
noneMatch(predicate: (item: unknown) => boolean): boolean
For empty stream returns true.
import { Stream } from "itertools-ts";
const grades = [45, 50, 61, 0];
const isPassingGrade = (grade) => grade >= 70;
const trueResult = Stream.of(grades)
.noneMatch(isPassingGrade);
// true
Returns true if stream and all given collections are the same.
sameWith(...collections: Array<Iterable<unknown> | Iterator<unknown>>): boolean
For empty collections list returns true.
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const trueResult = Stream.of(input)
.sameWith([1, 2, 3, 4, 5]);
// true
const falseResult = Stream.of(input)
.sameWith([5, 4, 3, 2, 1]);
// false
Returns true if stream collection and all given collections have the same lengths.
stream.sameCountWith(...collections: Array<Iterable<unknown> | Iterator<unknown>>): boolean
For empty collections list returns true.
import { Stream } from "itertools-ts";
const input = [1, 2, 3, 4, 5];
const trueResult = Stream.of(input)
.sameCountWith([5, 4, 3, 2, 1]);
// true
const falseResult = Stream.of(input)
.sameCountWith([1, 2, 3]);
// false
Peek at each element between other Stream operations to do some action without modifying the stream.
stream.peek(callback: (datum: unknown) => void): Stream
import { Stream } from "itertools-ts";
const result = Stream.of(['some', 'items'])
.peek((x) => console.log(x)) // 'some', 'items'
.toArray();
console.log(result);
// ['some', 'items']
Peek at the entire stream between other Stream operations to do some action without modifying the stream.
stream.peekStream(callback: (datum: Stream) => void): Stream
import { Stream } from "itertools-ts";
const result = Stream.of(['some', 'items'])
.peekStream((stream) => console.log(stream.toArray())) // ['some', 'items']
.toArray();
console.log(result);
// ['some', 'items']
Pipes are a way to chain multiple operations together.
Types notation:
type PipeOperation<TInput, TOutput> = (input: TInput) => TOutput;
type PipeOperationSequence<TFlow extends any[]> =
TFlow extends [infer T1, infer T2, ...infer Rest]
? [PipeOperation<T1, T2>, ...PipeOperationSequence<[T2, ...Rest]>]
: [];
type Pipe<TFlow extends any[]> = PipeOperation<First<TFlow>, Last<TFlow>> & {
add: TFlow extends []
? <TInput, TOutput>(operation: PipeOperation<TInput, TOutput>) => Pipe<[TInput, TOutput]>
: <T>(operation: PipeOperation<Last<TFlow>, T>) => Pipe<[...TFlow, T]>;
};
Pipe creation function:
function createPipe<T1, T2, ..., TN>(...operations: [PipeOperation<T1, T2>, PipeOperation<T2, T3>, ..., PipeOperation<TN-1, TN>]): PipeOperation<T1, TN>
Example with explicit type specification:
import { createPipe } from "itertools-ts";
const pipe = createPipe<[
Iterable<number>, // INPUT => set.distinct
Iterable<number>, // set.distinct => single.map
Iterable<number>, // single.map => single.filter
Iterable<number>, // single.filter => reduce.toSum
number // reduce.toSum => OUTPUT
]>(
set.distinct,
(input) => single.map(input, (x) => x ** 2),
(input) => single.filter(input, (x) => x < 10),
reduce.toSum,
);
const result1 = pipe([1, 1, 2, 2, 3, 4, 5]); // 14
// You can reuse the pipe
const result2 = pipe([1, 1, 1, 2, 2, 2]); // 5
Example with implicit type specification (works up to 16 operations if you use TypeScript):
import { createPipe } from "itertools-ts";
const pipe = createPipe(
set.distinct<number>,
(input) => single.map(input, (x) => x ** 2),
(input) => single.filter(input, (x) => x < 10),
reduce.toSum,
);
const result1 = pipe([1, 1, 2, 2, 3, 4, 5]); // 14
// You can reuse the pipe
const result2 = pipe([1, 1, 1, 2, 2, 2]); // 5
Example with creating pipe using chain calls:
import { createPipe } from "itertools-ts";
const pipe = createPipe()
.add(set.distinct<number>)
.add((input) => single.map(input, (x) => x**2))
.add((input) => single.filter(input, (x) => x < 10))
.add(reduce.toSum);
const result1 = pipe([1, 1, 2, 2, 3, 4, 5]); // 14
const result2 = pipe([1, 1, 1, 2, 2, 2]); // 5
// You can create a new pipe adding some operations
const extendedPipe = pipe
.add((x) => x * 2)
.add((x) => x + 1);
const result3 = extendedPipe([1, 1, 2, 2, 3, 4, 5]); // 29
const result4 = extendedPipe([1, 1, 1, 2, 2, 2]); // 11
Asynchronous pipe example:
import { createPipe } from "itertools-ts";
const asyncPipe = createPipe<[
AsyncIterable<number>, // INPUT => set.distinctAsync
AsyncIterable<number>, // set.distinctAsync => single.mapAsync
AsyncIterable<number>, // single.mapAsync => single.filterAsync
AsyncIterable<number>, // single.filterAsync => reduce.toSumAsync
Promise<number> // reduce.toSumAsync => OUTPUT
]>(
set.distinctAsync,
(input) => single.mapAsync(input, (x) => x**2),
(input) => single.filterAsync(input, (x) => x < 10),
reduce.toSumAsync,
);
const asyncInput1 = [1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x));
const result1 = await asyncPipe(asyncInput1); // 14
// You can reuse the pipe
const asyncInput2 = [1, 1, 1, 2, 2, 2].map((x) => Promise.resolve(x));
const result4 = await asyncPipe(asyncInput2); // 5
// You can create a new pipe adding some asynchronous operations
const extendedAsyncPipe = asyncPipe.add(async (x) => (await x) * 2);
const result5 = await extendedAsyncPipe(asyncInput2); // 10
You can also use pipe for non-iterables:
import { createPipe } from "itertools-ts";
const pipe = createPipe(
(x: number) => x+1,
(x) => x**3,
(x) => Math.sqrt(x),
(x) => Math.round(x)
);
const result1 = pipe(2); // 5
const asyncPipe = createPipe(
async (x: Promise<number>) => (await x)+1,
async (x) => (await x)**3,
async (x) => Math.sqrt(await x),
async (x) => Math.round(await x)
);
const result2 = await pipe(Promise.resolve(2)); // 5
IterTools functionality is not limited to TypeScript and Python. Other languages have similar libraries. Familiar functionality is available when working in other languages.
- IterTools PHP
- IterTools Python: The original!
npm i
npm run test
IterTools TS is licensed under the MIT License.