MunGell / awesome-for-beginners

A list of awesome beginners-friendly projects.
65.72k stars 6.85k forks source link

Add itertools-ts to TypeScript and JavaScript sections #1395

Open Smoren opened 4 months ago

Smoren commented 4 months ago

itertools-ts · npm Coverage Status Build and test

Extended itertools port for TypeScript and JavaScript. Provides a huge set of functions for working with iterable collections (including async ones).

Loop Iteration Tools Example

import { multi } from 'itertools-ts';

for (const [letter, number] of multi.zip(['a', 'b'], [1, 2])) {
  console.log(`${letter}${number}`);  // a1, b2
}

// Async example
for await (const [letter, number] of multi.zipAsync(['a', 'b'].map((x) => Promise.resolve(x)), [1, 2].map((x) => Promise.resolve(x)))) {
  console.log(`${letter}${number}`);  // a1, b2
}

Stream Iteration Tools Example

import { Stream, AsyncStream } from 'itertools-ts';

const result1 = Stream.of([1, 1, 2, 2, 3, 4, 5])
  .distinct()             // [1, 2, 3, 4, 5]
  .map((x) => x**2)       // [1, 4, 9, 16, 25]
  .filter((x) => x < 10)  // [1, 4, 9]
  .toSum();               // 14

// Async example
const result2 = await AsyncStream.of([1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x)))
  .distinct()             // [1, 2, 3, 4, 5]
  .map((x) => x**2)       // [1, 4, 9, 16, 25]
  .filter((x) => x < 10)  // [1, 4, 9]
  .toSum();               // 14

All functions work on iterable collections and iterators:

Every function have an analog with "Async"-suffixed name for working with async iterable and iterators (e.g. zip and zipAsync):

If an asynchronous function takes other functions as input, they can also be asynchronous.

Stream and Async Stream

Streams provide a fluent interface to transform arrays and iterables (sync or async) through a pipeline of operations.

Streams are made up of:

  1. One stream source factory method to create the stream.
  2. Zero or more stream operators that transform the stream to a new stream.
  3. Terminal operation of either:

    • Stream terminal operation to transform the stream to a value or data structure.

      const result1 = Stream.of([1, 1, 2, 2, 3, 4, 5])
      .distinct()             // [1, 2, 3, 4, 5]
      .map((x) => x**2)       // [1, 4, 9, 16, 25]
      .filter((x) => x < 10)  // [1, 4, 9]
      .toSum();               // 14
      
      // Async example
      const result2 = await AsyncStream.of([1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x)))
      .distinct()             // [1, 2, 3, 4, 5]
      .map((x) => x**2)       // [1, 4, 9, 16, 25]
      .filter((x) => x < 10)  // [1, 4, 9]
      .toSum();               // 14
    • The stream is iterated via a for loop.

      const result1 = Stream.of([1, 1, 2, 2, 3, 4, 5])
      .distinct()             // [1, 2, 3, 4, 5]
      .map((x) => x**2)       // [1, 4, 9, 16, 25]
      .filter((x) => x < 10); // [1, 4, 9]
      
      for (const item of result1) {
      // 1, 4, 9
      }
      
      // Async example
      const result2 = AsyncStream.of([1, 1, 2, 2, 3, 4, 5].map((x) => Promise.resolve(x)))
      .distinct()             // [1, 2, 3, 4, 5]
      .map((x) => x**2)       // [1, 4, 9, 16, 25]
      .filter((x) => x < 10); // [1, 4, 9]
      
      for await (const item of result2) {
      // 1, 4, 9
      }