ArrayStream can be initialized with an array or a generator function, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5]);
or
function *gen(min: number, max: number) {
while (true) {
yield Math.floor(Math.random() * (max - min + 1)) + min;
}
}
const stream = new ArrayStream(gen(1, 100));
Alias for the skip
, which has the same functionality as the drop
iterator helper, c.f.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/drop
Returns a new iterator that will skip the first n items from the iterator, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.skip(2)
.collect();
console.log(stream); // [3, 4, 5]
Alias for all
, which will check if all items match a predicate, c.f.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/every
Consume the iterator and return a boolean if all the items cause the function to return true. Short circuits and returns false on the first item that returns false, i.e.
const allEven = new ArrayStream([2, 4, 6, 8, 10])
.all((item) => item % 2 === 0);
console.log(allEven) // true
or
const allEven = new ArrayStream([2, 4, 6, 8, 9])
.all((item) => item % 2 === 0);
console.log(allEven) // false
Alias for any
, which will check if any items match a predicate, c.f.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/some
Iterate through the iterator and return find the first item where the function returns true. It is short circuiting, i.e.
const hasEven = new ArrayStream([1, 2, 3, 4, 5])
.any((item) => item % 2 === 0);
console.log(hasEven) // true
or
const hasEven = new ArrayStream([1, 3, 5, 7, 9])
.any((item) => item % 2 === 0);
console.log(hasEven) // false
Alias for collect
, which will consume the iterator and return the items in an array, c.f.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/toArray
Consume the iterator and return the items in an array. It is identical in functionality to a reduce method with an array that pushes the items, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5]).collect();
// stream = [1, 2, 3, 4, 5]
const stream2 = new ArrayStream([1,2,3,4,5]).reduce((acc, next) => {
acc.push(next);
return acc;
}, []);
Consume the iterator and return a boolean if all the items cause the function to return true. Short circuits and returns false on the first item that returns false, i.e.
const allEven = new ArrayStream([2, 4, 6, 8, 10])
.all((item) => item % 2 === 0);
console.log(allEven) // true
or
const allEven = new ArrayStream([2, 4, 6, 8, 9])
.all((item) => item % 2 === 0);
console.log(allEven) // false
Iterate through the iterator and return find the first item where the function returns true. It is short circuiting, i.e.
const hasEven = new ArrayStream([1, 2, 3, 4, 5])
.any((item) => item % 2 === 0);
console.log(hasEven) // true
or
const hasEven = new ArrayStream([1, 3, 5, 7, 9])
.any((item) => item % 2 === 0);
console.log(hasEven) // false
Removes duplicate items from the stream asynchronously based on the provided callback function. If no callback is provided, a shallow comparison is used.
Functionally identical to the dedupe
method, but it allows for an asynchronous callback but returns
an AsyncArrayStream
instead of an ArrayStream
, e.g.
const stream = await new ArrayStream([1, 2, 3, 4, 5, 1, 2, 3, 4, 5])
.asyncDedupe(item => Promise.resolve(item))
.collect();
console.log(stream); // [1, 2, 3, 4, 5]
Return a new iterator that appends the parameter stream to the current stream, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.chain([6, 7, 8, 9, 10])
.collect();
console.log(stream);
Consume the iterator and return the items in an array. It is identical in functionality to a reduce method with an array that pushes the items, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5]).collect();
// stream = [1, 2, 3, 4, 5]
const stream2 = new ArrayStream([1,2,3,4,5]).reduce((acc, next) => {
acc.push(next);
return acc;
}, []);
Removes duplicate items from the stream based on a provided callback function. If no callback is provided, a shallow comparison is used, e.g..
const stream = new ArrayStream([1, 2, 3, 4, 5, 1, 2, 3, 4, 5])
.dedupe()
.collect();
console.log(stream); // [1, 2, 3, 4, 5]
Returns an iterator that will yield a tuple of the iterated item accompanied by an index, i.e.
const stream = new ArrayStream([100, 200, 300, 400, 500])
.enumerate()
.collect();
console.log(stream);
Add a filter operation to the iterator that will be resolved when the iterator is finalized. A filter operation takes an iterator of type A and returns an iterator of type A but removes all items that do not return true from the filter function, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.filter((item) => item % 2 === 0)
.collect();
console.log(stream); // [2, 4]
Add a filterMap operation to the iterator that will be resolved when the iterator is finalized. A filterMap operation takes an iterator of type A and returns an iterator of type B but also removes any items that return null, false, or undefined, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.filterMap((item) => (item % 2 === 0 ? item * 2 : null))
.collect();
console.log(stream); // [4, 8]
NOTE: Map functions change the type of the iterator, but if you call the function without reassigning the variable or chaining methods, then the type will be incorrect, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
stream.map(item => String.fromCharCode(item + 65));
then the type of stream will be ArrayStream<number, Breaker<number>>
instead of
ArrayStream<string, Breaker<string>>
. Instead, do one of these two:
const stream = new ArrayStream([1, 2, 3, 4, 5])
.map(item => String.fromCharCode(item + 65));
or
let stream = new ArrayStream([1, 2, 3, 4, 5]);
stream = stream.map(item => String.fromCharCode(item + 65));
Consume the iterator and return the first item that causes the function to return true.
If the item is not found, it will return null
. This method can be used on an infinite
generator but will never return if the item is never found. The function short circuits
on the first item that returns true and will not consume the rest of the iterator, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.find((item) => item % 2 === 0);
console.log(stream); // 2
or
const stream = new ArrayStream([1, 3, 5, 7, 9])
.find((item) => item % 2 === 0);
console.log(stream); // null
Consume the iterator and return the index of first item that causes the function to
return true. If the item is not found, it will return -1
. This method can be used
on an infinite generator but will never return if the item is never found.
The function short circuits on the first item that returns true and will not consume
the rest of the iterator, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.findIndex((item) => item % 2 === 0);
console.log(stream); // 1
or
const stream = new ArrayStream([1, 3, 5, 7, 9])
.findIndex((item) => item % 2 === 0);
console.log(stream); // -1
Consume the iterator and return the first item that causes the function to
return true starting from the last item in the iteraotr. If the item is not
found, it will return null
. This method cannot be used on an infinite
generator because it needs to consume the entire iterator to start from the end.
The function does not short circuit and will consume the entire iterator, i.e.
const null = new ArrayStream([1, 2, 3, 4, 5])
.findLast((item) => item % 2 === 0);
console.log(null); // 4
or
const item = new ArrayStream([1, 3, 5, 7, 9])
.findLast((item) => item % 2 === 0);
console.log(item); // null
Consume the iterator and return the index of the first item that causes the function to
return true starting from the last item in the iteraotr. If the item is not
found, it will return null
. This method cannot be used on an infinite
generator because it needs to consume the entire iterator to start from the end.
The function does not short circuit and will consume the entire iterator, i.e.
const position = new ArrayStream([1, 2, 3, 4, 5])
.findLastIndex((item) => item % 2 === 0);
console.log(position); // 4
or
const position = new ArrayStream([1, 3, 5, 7, 9])
.findLastIndex((item) => item % 2 === 0);
console.log(position); // -1
Consume the iterator and collect all items into an array flattened to the specified depth, i.e.
const stream = new ArrayStream([[1, 2], [3, [4, 5]], [5, [6, [7, 8]]]]).flat(2);
// stream = [1, 2, 3, 4, 5, 5, 6, [7, 8]]
Optional
d: DReturns an iterator that will apply a function that will map the iterated item to an array then flatten it, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.flatMap((item) => [item, item + 100])
.collect();
console.log(stream);
Add a forEach operation to the iterator that will be resolved when the iterator is finalized. A forEach operation takes an iterator of type A and returns nothing. A forEach function should be impure and cause side effects, i.e.
let sum = 0;
const sum2 = new ArrayStream([1, 2, 3, 4, 5])
.forEach((item) => sum += item)
.reduce((acc, next) => acc + next, 0);
console.log(sum === sum2); // true
NOTE: This method differs from the Iterator.prototype.forEach
method in two ways:
undefined
Returns an iterator that will exhaust as soon as the iterator yields a null or undefined value, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5, null, 6, 7, 8, 9, 10])
.fuse()
.collect();
console.log(stream);
Consume the iterator and return if any item is equal to the input. This is short circuiting and will return after any item is equal to the input. NOTE: This will not work correctly for reference values, i.e.
const hasTwo = new ArrayStream([1, 2, 3, 4, 5])
.includes(2);
console.log(hasTwo); // true
but this will not work:
const obj = { a: 1 };
const hasObj = new ArrayStream([{ a: 1 }, { a: 2 }])
.includes(obj);
console.log(hasObj);
A forEach operation that is used for debugging purposes which defaults to console.log.
new ArrayStream([1, 2, 3, 4, 5])
.inspect()
.collect();
// 1-5 will be logged
Return a new iterator that will include an item between every value returned by the iterator. The item can be a value of a function that returns the value, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.intersperse(0)
.collect();
console.log(stream); // [1, 0, 2, 0, 3, 0, 4, 0, 5]
or
const stream = new ArrayStream([1, 2, 3, 4, 5])
.intersperse((x) => x * 5)
.collect();
console.log(stream); // [1, 5, 2, 10, 3, 15, 4, 20, 5]
Add a map operation to the iterator that will be resolved when the iterator is finalized. A map operation takes an iterator of type A and returns an iterator of type B. A map function is different from forEach in that it should be pure and not have side effects, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.map((item) => item * 2)
.collect();
console.log(stream); // [2, 4, 6, 8, 10]
NOTE: Map functions change the type of the iterator, but if you call the function without reassigning the variable or chaining methods, then the type will be incorrect, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
stream.map(item => String.fromCharCode(item + 65));
then the type of stream will be ArrayStream<number, Breaker<number>>
instead of
ArrayStream<string, Breaker<string>>
. Instead, do one of these two:
const stream = new ArrayStream([1, 2, 3, 4, 5])
.map(item => String.fromCharCode(item + 65));
or
let stream = new ArrayStream([1, 2, 3, 4, 5]);
stream = stream.map(item => String.fromCharCode(item + 65));
Consume the iterator up to the nth item and returns it. Returns null if the iterator is exhausted before reaching n, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.nth(2);
console.log(stream); // 3
or
const stream = new ArrayStream([1, 2, 3, 4, 5])
.nth(10);
console.log(stream); // null
Consume the iterator and return a tuple of two arrays, the left being
those that caused the function to return true
, and the right the others, i.e.
const [left, right] = new ArrayStream([1, 2, 3, 4, 5])
.partition((item) => item % 2 === 0);
console.log(left); // [2, 4]
console.log(right); // [1, 3, 5]
View the next item in the iterator without consuming it.
const stream = new ArrayStream([1, 2, 3, 4, 5]);
console.log(stream.peek()); // 1
console.log(stream.peek()); // 1
const items = stream.collect();
console.log(items); // [1, 2, 3, 4, 5]
console.log(stream.peek()); // null
Consume the iterator and collect all items into the chosen data structure starting from the first item, i.e.
const stream = new ArrayStream(["a", "b", "c", "d", "e"])
.reduce((acc, next) => acc + next, "");
console.log(stream); // "abcde"
Consume the iterator and collect all items into the chosen data structure starting from the last item, i.e.
const stream = new ArrayStream(["a", "b", "c", "d", "e"])
.reduceRight((acc, next) => acc + next, "");
console.log(stream); // "edcba"
Returns a new iterator that will skip the first n items from the iterator, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.skip(2)
.collect();
console.log(stream); // [3, 4, 5]
Return a new iterator that will only include items whose indexes are divisible by N, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.stepBy(2)
.collect();
console.log(stream);
Take the first n items from the iterator that will be resolved when the iterator is finalized, i.e.
function *gen() {
let count = 0;
while (true) {
yield count++;
}
}
const stream = new ArrayStream(gen())
.take(3)
.collect();
console.log(stream); // [1, 2, 3]
Return a new iterator that will yield the tuple of items from both data sources It will be exhausted as soon as either data source is exhausted, i.e.
const stream = new ArrayStream([1, 2, 3, 4, 5])
.zip([6, 7, 8, 9, 10])
.collect();
console.log(stream); // [[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
A class for performing a series of operations on a synchronous and iterable source of data. It aims to have a similar set of features as baseline Rust iterator. It is lazy and will only iterate and perform operations when a finalizer method is called.