Class ArrayStream<Input, Handler>

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.

function* range(start: number, end: number = -1, step: number = 1) {
let count = start;
while (count < end || end === -1) {
yield count;
count += step;
}
}
const stream = new ArrayStream(range(10))
// 20, 30, 40, 50, ...
.filterMap((item) => (item % 5 === 0 ? item ** 2 : null))
// 20, 30, 40, 50, 60
.take(5)
.reduce((acc, next) => acc + next, 0);

console.log(stream); // 200

Type Parameters

Constructors

Properties

drop: ((n: number) => ArrayStream<Input, Handler>) = ...

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

Type declaration

    • (n): ArrayStream<Input, Handler>
    • 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]

      Parameters

      • n: number

      Returns ArrayStream<Input, Handler>

every: ((fn: ((item: Input) => boolean)) => HandlerReturnType<Handler, Input, boolean>) = ...

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

Type declaration

    • (fn): HandlerReturnType<Handler, Input, boolean>
    • 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

      Parameters

      • fn: ((item: Input) => boolean)
          • (item): boolean
          • Parameters

            Returns boolean

      Returns HandlerReturnType<Handler, Input, boolean>

some: ((fn: ((item: Input) => boolean)) => HandlerReturnType<Handler, Input, boolean>) = ...

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

Type declaration

    • (fn): HandlerReturnType<Handler, Input, boolean>
    • 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

      Parameters

      • fn: ((item: Input) => boolean)
          • (item): boolean
          • Parameters

            Returns boolean

      Returns HandlerReturnType<Handler, Input, boolean>

toArray: (() => HandlerReturnType<Handler, Input, Input[]>) = ...

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

Type declaration

    • (): HandlerReturnType<Handler, Input, Input[]>
    • 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;
      }, []);

      Returns HandlerReturnType<Handler, Input, Input[]>

Methods

  • 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

    Parameters

    • fn: ((item: Input) => boolean)
        • (item): boolean
        • Parameters

          Returns boolean

    Returns HandlerReturnType<Handler, Input, boolean>

  • 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

    Parameters

    • fn: ((item: Input) => boolean)
        • (item): boolean
        • Parameters

          Returns boolean

    Returns HandlerReturnType<Handler, Input, boolean>

  • 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]

    Type Parameters

    • T

    Parameters

    • cb: ((item: Input) => T | Promise<T>) = ...
        • (item): T | Promise<T>
        • Parameters

          Returns T | Promise<T>

    Returns AsyncArrayStream<Input, Handler>

  • 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;
    }, []);

    Returns HandlerReturnType<Handler, Input, Input[]>

  • Consume the iteraor and return however many items it contains, i.e.

    const stream = new ArrayStream(["a", "b", "c"])
    .count();
    console.log(stream); // 3

    Returns HandlerReturnType<Handler, Input, number>

  • 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]

    Type Parameters

    • T

    Parameters

    • cb: ((item: Input) => T) = ...
        • (item): T
        • Parameters

          Returns T

    Returns ArrayStream<Input, Handler>

  • 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]

    Parameters

    • fn: ((input: Input) => boolean)
        • (input): boolean
        • Parameters

          Returns boolean

    Returns ArrayStream<Input, Handler>

  • 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));

    Type Parameters

    • End

    Parameters

    • fn: ((input: Input) =>
          | undefined
          | null
          | false
          | End)
        • (input):
              | undefined
              | null
              | false
              | End
        • Parameters

          Returns
              | undefined
              | null
              | false
              | End

    Returns ArrayStream<End, NarrowHandlerType<Handler, Input, End>>

  • 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

    Parameters

    • fn: ((item: Input) => boolean)
        • (item): boolean
        • Parameters

          Returns boolean

    Returns HandlerReturnType<Handler, Input, null | Input>

  • 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

    Parameters

    • fn: ((item: Input) => boolean)
        • (item): boolean
        • Parameters

          Returns boolean

    Returns HandlerReturnType<Handler, Input, number>

  • 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

    Parameters

    • fn: ((item: Input) => boolean)
        • (item): boolean
        • Parameters

          Returns boolean

    Returns HandlerReturnType<Handler, Input, null | Input>

  • 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

    Parameters

    • fn: ((item: Input) => boolean)
        • (item): boolean
        • Parameters

          Returns boolean

    Returns HandlerReturnType<Handler, Input, number>

  • 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]]

    Type Parameters

    • D extends number = 1

    Parameters

    • Optionald: D

    Returns HandlerReturnType<Handler, Input, FlatArray<Input, D>[]>

  • Returns 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);

    Type Parameters

    • End

    Parameters

    Returns ArrayStream<End, NarrowHandlerType<Handler, Input, End>>

  • 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:

    1. ArrayStream.prototype.forEach lazily evaluates the iterator and will run on infinite generators. It does not exhaust the generator.
    2. ArrayStream.prototype.forEach will yield the iterated item and does not return undefined

    Parameters

    • fn: ((input: Input) => void)
        • (input): void
        • Parameters

          Returns void

    Returns ArrayStream<Input, Handler>

  • 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);

    Returns ArrayStream<Required<Input>, RequiredHandler<Handler>>

  • 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);

    Parameters

    Returns HandlerReturnType<Handler, Input, boolean>

  • 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]

    Type Parameters

    • Item

    Parameters

    Returns ArrayStream<Input | Item, NarrowHandlerType<Handler, Input, Input | Item>>

  • 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));

    Type Parameters

    • End

    Parameters

    Returns ArrayStream<End, NarrowHandlerType<Handler, Input, End>>

  • 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

    Parameters

    • n: number

    Returns HandlerReturnType<Handler, Input, null | Input>

  • 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]

    Parameters

    • fn: ((input: Input) => boolean)
        • (input): boolean
        • Parameters

          Returns boolean

    Returns HandlerReturnType<Handler, Input, [Input[], Input[]]>

  • 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

    Returns null | Input

  • Use this method to manually consume the iterator.

    Returns Generator<Input, void, unknown>

  • 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"

    Type Parameters

    • End

    Parameters

    Returns HandlerReturnType<Handler, Input, End>

  • 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"

    Type Parameters

    • End

    Parameters

    Returns HandlerReturnType<Handler, Input, End>

  • 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]

    Parameters

    • n: number

    Returns ArrayStream<Input, Handler>