itertools-ts
Version: 
Extended itertools port for TypeScript and JavaScript. Provides a huge set of functions for working with iterable collections (including async ones)
250 lines (227 loc) • 6.79 kB
text/typescript
import { toAsyncIterable, toIterable } from "./transform";
import { Numeric } from "./types";
/**
 * Accumulate the running average (mean) over a list of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running average leads off with the initial value.
 */
export function* runningAverage(
  numbers: Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): Iterable<number> {
  let n = 0;
  for (const total of runningTotal(toIterable(numbers), initialValue)) {
    n++;
    yield (total / n);
  }
}
/**
 * Accumulate the running average (mean) over a async collection of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running average leads off with the initial value.
 */
export async function* runningAverageAsync(
  numbers: AsyncIterable<Numeric> | AsyncIterator<Numeric> | Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): AsyncIterable<number> {
  let n = 0;
  for await (const total of runningTotalAsync(
    toAsyncIterable(numbers),
    initialValue
  )) {
    n++;
    yield (total / n);
  }
}
/**
 * Accumulate the running difference over a list of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running difference leads off with the initial value.
 */
export function* runningDifference(
  numbers: Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): Iterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let difference = initialValue ?? 0;
  for (const num of toIterable(numbers)) {
    difference -= Number(num);
    yield difference;
  }
}
/**
 * Accumulate the running difference over a async collection of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running difference leads off with the initial value.
 */
export async function* runningDifferenceAsync(
  numbers: AsyncIterable<Numeric> | AsyncIterator<Numeric> | Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): AsyncIterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let difference = initialValue ?? 0;
  for await (const num of toAsyncIterable(numbers)) {
    difference -= Number(num);
    yield difference;
  }
}
/**
 * Accumulate the running max over a list of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running max leads off with the initial value.
 */
export function* runningMax(
  numbers: Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): Iterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let max = initialValue ?? -Infinity;
  for (const num of toIterable(numbers)) {
    max = Math.max(max, num as number);
    yield max;
  }
}
/**
 * Accumulate the running max over a async collection of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running max leads off with the initial value.
 */
export async function* runningMaxAsync(
  numbers: AsyncIterable<Numeric> | AsyncIterator<Numeric> | Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): AsyncIterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let max = initialValue ?? -Infinity;
  for await (const num of toAsyncIterable(numbers)) {
    max = Math.max(max, num as number);
    yield max as number;
  }
}
/**
 * Accumulate the running min over a list of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running min leads off with the initial value.
 */
export function* runningMin(
  numbers: Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): Iterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let min = initialValue ?? Infinity;
  for (const num of toIterable(numbers)) {
    min = Math.min(min, num as number);
    yield min as number;
  }
}
/**
 * Accumulate the running min over a async collection of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running min leads off with the initial value.
 */
export async function* runningMinAsync(
  numbers: AsyncIterable<Numeric> | AsyncIterator<Numeric> | Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): AsyncIterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let min = initialValue ?? Infinity;
  for await (const num of toAsyncIterable(numbers)) {
    min = Math.min(min, num as number);
    yield min as number;
  }
}
/**
 * Accumulate the running product over a list of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running product leads off with the initial value.
 */
export function* runningProduct(
  numbers: Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): Iterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let product = initialValue ?? 1;
  for (const num of toIterable(numbers)) {
    product *= Number(num as number);
    yield product as number;
  }
}
/**
 * Accumulate the running product over a async collection of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running product leads off with the initial value.
 */
export async function* runningProductAsync(
  numbers: AsyncIterable<Numeric> | AsyncIterator<Numeric> | Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): AsyncIterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let product = initialValue ?? 1;
  for await (const num of toAsyncIterable(numbers)) {
    product *= Number(num as number);
    yield product as number;
  }
}
/**
 * Accumulate the running total over a list of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running total leads off with the initial value.
 */
export function* runningTotal(
  numbers: Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): Iterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let total = initialValue ?? 0;
  for (const num of toIterable(numbers)) {
    total += Number(num as number);
    yield total as number;
  }
}
/**
 * Accumulate the running total over a async collection of numbers
 *
 * @param numbers
 * @param initialValue (Optional) If provided, the running total leads off with the initial value.
 */
export async function* runningTotalAsync(
  numbers: AsyncIterable<Numeric> | AsyncIterator<Numeric> | Iterable<Numeric> | Iterator<Numeric>,
  initialValue?: number
): AsyncIterable<number> {
  if (initialValue !== undefined) {
    yield initialValue;
  }
  let total = initialValue ?? 0;
  for await (const num of toAsyncIterable(numbers)) {
    total += Number(num as number);
    yield total as number;
  }
}