class Enumerable
implements AsyncIterable<T>

Fluent wrapper for AsyncIterable with composable operations.

Enumerable provides a rich set of operations for working with async data streams:

  • Transformations: map, filter, flatMap
  • Aggregations: reduce, count, collect
  • Utilities: take, drop, concat, zip
  • Process integration: run, lines, toStdout
  • Concurrency: concurrentMap, concurrentUnorderedMap

Create instances using enumerate, not the constructor directly.

Constructors

new
Enumerable(iter: AsyncIterable<T>)

Construct a new enumerable wrapper.

Type Parameters

Properties

Convert to text lines, grouped into arrays.

For large data or data that is broken into many small lines, this can improve performance over lines.

readonly
first: Promise<T>

Get the first item in the sequence.

Consumes the enumeration and returns the first element.

readonly
lines: Lines<T>

Convert byte stream to text lines.

Important: This is a property, not a method. Use .lines not .lines().

Returns an Enumerable<string> where each item is a line of text. Lines are split on \n or \r\n. Line endings are not included in the output.

Note that this should probably only be used with small data. Consider chunkedLines to improve performance with larger data.

Methods

[Symbol.asyncIterator](): AsyncGenerator<T, void, unknown>

Implement AsyncIterable<T>.

collect(): Promise<T[]>

Collect all items from this async iterable into an array.

This consumes the entire iterable and returns a Promise that resolves to an array containing all items.

concat(other: AsyncIterable<T>): Enumerable<T>

Concatenate this sequence with another.

concurrentMap<U>(
mapFn: (item: T) => Promise<U>,
): Enumerable<U>

Map the sequence from one type to another, concurrently.

Results are returned in order. The order of processing is concurrent, and therefore somewhat arbitrary.

concurrentUnorderedMap<U>(
mapFn: (item: T) => Promise<U>,
): Enumerable<U>

Map the sequence from one type to another, concurrently.

Items are iterated out of order. This allows maximum concurrency at all times, but the output order cannot be assumed to be the same as the input order.

This guarantees maximum concurrency whereas concurrentMap does not if the workload isn't balanced. Prefer concurrentUnorderedMap to concurrentMap for best/consistent performance.

count(filterFn?: (item: T) => boolean | Promise<boolean>): Promise<number>

Count the number of items; optionally with a filter.

drop<N extends number = 1>(n?: N): Enumerable<T>

Skip the first n items and return the rest.

enum(): Enumerable<[T, number]>

Adds a counter from 0 to n-1 of the items being enumerated.

Returns tuples of [item, index] where index starts at 0.

every(everyFn: (element: T) => boolean | Promise<boolean>): Promise<boolean>

Test if every item satisfies a condition.

filter(filterFn: (item: T) => boolean | Promise<boolean>): Enumerable<T>

Keep only items that pass a test.

filterNot(filterFn: (item: T) => boolean | Promise<boolean>): Enumerable<T>

Filter the sequence to exclude the items that pass a test. This returns the inverse of filter.

find(findFn: (element: T) => unknown | Promise<unknown>): Promise<T | undefined>

Find the first item that matches a condition.

flatMap<U>(mapFn: (item: T) => U | Promise<U>): Enumerable<ElementType<U>>

Map each item to an iterable and flatten the results.

Equivalent to calling map() followed by flatten().

flatten(): Enumerable<ElementType<T>>

Flatten the iterable.

forEach(forEachFn: (item: T) => void | Promise<void>): Promise<void>

Perform an operation for each item in the sequence.

map<U>(mapFn: (item: T) => U | Promise<U>): Enumerable<U>

Map the iterator from one type to another.

reduce(reduceFn: (
acc: T,
item: T,
index: number,
) => T | Promise<T>
): Promise<T>

Reduce the sequence to a single value.

Executes a reducer function on each element, passing the accumulated result from one element to the next.

reduce<U>(
reduceFn: (
acc: U,
item: T,
index: number,
) => U | Promise<U>
,
zero: U,
): Promise<U>

Reduce the sequence to a single value with an initial value.

run<S>(
options: ProcessOptions<S>,
...cmd: Cmd,
): Run<S, T>

Run a process, piping this iterable's output to its stdin.

This allows chaining processes together like shell pipes. The current iterable's data is written to the new process's stdin, and the new process's stdout becomes the new iterable.

run(...cmd: Cmd): Run<unknown, T>

Run a process.

some(someFn: (element: T) => boolean | Promise<boolean>): Promise<boolean>

Test if any item satisfies a condition.

take<N extends number = 1>(n?: N): Enumerable<T>

Take the first n items from the sequence.

tee<N extends number = 2>(n?: N): Tuple<Enumerable<T>, N>

Split the sequence into multiple identical streams.

Useful when you need to process the same data in different ways. Uses buffering internally, so be mindful of memory with large datasets.

toStdout(): Promise<void>

Dump output to stdout. Non-locking.

Handles strings, string arrays, Uint8Arrays, and arrays of those. Strings automatically have newlines appended.

Transform the iterable from one type to another with an opportunity to catch and handle errors.

unzip<
A,
B,
>
(): Unzip<T>

Unzip a collection of [A, B] into Enumerable<A> and Enumerable<B>.

Note that this operations uses tee, so it will use memory during the iteration.

Example

const [a, b] = enumerate([[1, "A"], [2, "B"], [3, "C"]]).unzip();

// a is number[] -> [1, 2, 3]
// b is string[] -> ["A", "B", "C"]
writeBytesTo(writer: Writer & Closer): ByteSink<T>

Dump output to a writer and close it.

This is a low-level asynchronous write of bytes without locking.

writeTo(
writer: Writable<T> | WritableStream<T>,
options?: { noclose?: boolean; },
): Promise<void>

Write all data to the writer.

Example

Write some numbers to stdout.

range({to: 99})
  .map(n => n.toString())
  .transform(toBytes)
  .writeTo(Deno.stdout.writable, {noclose: true});
zip<U>(other: AsyncIterable<U>): Enumerable<[T, U]>

Zip two Enumerables together. If collections are unequal length, the longer collection is truncated.

Example

const a = range({ from: 1, until: 3 });
const b = enumerate(["A", "B", "C"]);

const result = a.zip(b);

// [[1, "A"], [2, "B"], [3, "C"]]