Smoren / itertools-ts

TypeScript Iteration Tools Library
MIT License
46 stars 7 forks source link

New IterTools Functionality Discussion #50

Open Smoren opened 7 months ago

Smoren commented 7 months ago

This thread is for discussion new functionality to implement in IterTools. Please reply with suggestions for new functionality.

Here are some of the functions I am considering implementing. Some are more useful than others.

Single

Shuffle

Shuffle the elements in the iterable.

function *shuffle<T>(data: Iterable<T> | Iterator<T>): Iterable<T>

Filter RegEx

Filter for elements where the regular expression matches.

function *filterRegEx<T>(data: Iterable<T> | Iterator<T>, regex: string): Iterable<T>

Permutations

All permutations of size length.

function *permutations<T>(data: Iterable<T> | Iterator<T>, length: number) Iterable<T>

Combinations

All combinations of size length.

function *combinations<T>(data: Iterable<T> | Iterator<T>, length: int) Iterable<T>

Combinations With Replacement

All combinations, with repeated elements, of size length.

function *combinationsWithReplacement<T>(data: Iterable<T> | Iterator<T>, length: number) Iterable<T>

Multi

Unzip

Reverse of zip. E.g.: ['a', 1], ['b', 2], ['c', 3] => ['a', 'b', 'c'], [1, 2, 3]

function *unzip(...iterables: Array<Iterable | Iterator>): Array

Note: specify types.

Reduce

To Random Value

Reduce the iterable to any random value in the iterable.

function *toRandomValue<T>(data: Iterable<T> | Iterator<T>): T

PHP implementation example

To Nth

Reduce the iterable to the value at the nth position.

function *toNth<T>(data: Iterable<T> | Iterator<T>): T

PHP implementation example

To Frequencies

Reduce the iterable to a frequency distribution showing how often each different value in the data occurs.

function *toFrequencies<T>(data: Iterable<T> | Iterator<T>): Array<number>

To String

Reduces to a string joining all elements.

function *toString<T>(data: Iterable<T> | Iterator<T>, separator: string, prefix: string, suffix: string): string

PHP implementation example

Summary

Not All Match

True if not all the elements are true according to the predicate.

function *notAllMatch<T>(data: Iterable<T> | Iterator<T>, predicate: (datum: T) => boolean): boolean

Is Empty

True if the iterable is empty.

function *isEmpty<T>(data: Iterable<T> | Iterator<T>): boolean

PHP implementation example

All Equal

True if all elements of the iterable are equal.

funcion *allEqual<T>(data: Iterable<T> | Iterator<T>): boolean

Note: Consider maybe adding a strict parameter, or alternate method allSame.

Are Permutations

True if iterables are permutations of each other.

function *arePermutations<T>(...iterables: Array<Iterable<T> | Iterator<T>>): boolean

PHP implementation example

Is Partitioned

Returns true if all elements of given collection that satisfy the predicate appear before all elements that don't.

function *isPartitioned<T>(...iterable: Iterable<T> | Iterator<T>, predicate?: (datum: T) => boolean): boolean

PHP implementation example

Set

Difference

Compares first iterable against one or more other iterables and iterates the values in array that are not present in any of the other arrays.

function *difference<T>(
    ...iterables: Array<Iterable<T> | Iterator<T>>
): Iterable<T>

Transform

Distribute

Distribute the elements of the iterable evenly into n smaller iterables. Ex: ([1, 2, 3, 4], 2) => [1, 3], [2, 4]

function *distribute<T>(data: Iterable<T> | Iterator<T>, n: number): Iterable<Array<T>>

Divide

Divide the elements of the iterable evenly into n smaller iterables, maintaining order. Ex: ([1, 2, 3, 4], 2) => [1, 2], [3, 4]

function *divide<T>(data: Iterable<T> | Iterator<T>, n: number): Iterable<Array<T>>

Random

Choice

Generate random selections from an array of values.

If optional param repetitions not given then iterate infinitely.

function *choice<T>(items: Array<T>, repetitions?: number): Iterable<T>

PHP implementation example

Coin Flip

Generate random coin flips (0 or 1).

If optional param repetitions not given then iterate infinitely.

function *coinFlip(repetitions?: number): Iterable<number>

PHP implementation example

Bool

Generate random boolean values.

If optional param repetitions not given then iterate infinitely.

function *bool(repetitions?: number): Iterable<boolean>

Number

Generate random integer numbers.

If optional param repetitions not given then iterate infinitely.

function *booleans(min: number, max: number, repetitions?: number): Iterable<boolean>

PHP implementation example

Percentage

Generate a random percentage between 0 and 1.

If optional param repetitions not given then iterate infinitely.

function *percentage(repetitions?: number): Iterable<number>

PHP implementation example

RockPaperScissors

Generate random rock-paper-scissors hands. Return values: "rock", "paper", "scissors".

If optional param repetitions not given then iterate infinitely.

function *rockPaperScissors(repetitions?: number): Iterable<string>

PHP implementation example

zveroboy commented 6 months ago

@Smoren First of all, thank you for a wonderful library.

I guess it's pretty hard to implement a FP version of it where functions are curried and parameters are inversed using TS, right?

An example:

const takeWhile = _.curry(function* takeWhile(predicateFn, iterable) {
  for (const item of iterable) {
    if (predicateFn(item)) {
      yield item;
    } else {
      break;
    }
  }
});

const limitAsync = _.curry(async function* limitAsync(count, iterable) {
  if (count < 0) {
    throw new TypeError(`Limit must be ≥ 0. Got ${count}`);
  }

  let i = 0;
  for await (const datum of iterable) {
    if (i >= count) {
      return;
    }
    yield datum;
    ++i;
  }
});

// …
const asyncIterable = httpClient.fetchSomePaginatedDataIterable();

const fetch100ItemsOrLess = _.compose(
  toArrayAsync,
  limitAsync(100),
  flatMapAsync(response => response.data),
);

const result = await fetch100ItemsOrLess(asyncIterable);
Smoren commented 6 months ago

Hi @zveroboy! Thank you for your feedback! I think you can use streams for such tasks.

import { AsyncStream } from 'itertools-ts';

const fetch100ItemsOrLess = async (response) => await AsyncStream.of(response)
  .flatMap(response => response.data)
  .limit(100)
  .toArray();

const result = await fetch100ItemsOrLess(asyncIterable);