Skip to content
This repository has been archived by the owner on Jan 28, 2023. It is now read-only.
/ Js-Seq Public archive

Small javascript functional sequence processing library

License

Notifications You must be signed in to change notification settings

Degubi/Js-Seq

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Javascript functional sequence processing library

Github issues GitHub package.json version Linecount GitHub Workflow Status Dependencies

  • The api is very similar to java8 streams
  • Lazy by default
  • Made because of boredom

Versions for other languages

Installation

Using npm: (via Github packages)

npm install @degubi/js-seq

Without npm:

Minified .js file is available in the 'build' directory, .ts file is available in the src directory

Usage (Docs)

Importing:

import { Sequence } from './seq.js';

Creating sequences:

Sequence.range(0, 10);                           // 1 to 10 excluding 10
Sequence.rangeClosed(0, 10)                      // 1 to 10 including 10
Sequence.range(0, 10, 2);                        // 1 to 10 stepping 2, excluding 10
Sequence.iterate(1, k => k * 2)                  // 1, 2, 4, 8.... this sequence is infinite
Sequence.iterate(1, k => k * 2, k => k < 50)     // Same as the last one but taking values less than 50 (same as doing a takeWhile)
Sequence.generate(readline)                      // Generate strings with reading from console
Sequence.from(1, 3, 3, 7, 4, 2, 0)               // Sequence of elements
Sequence.from([ 1, 2, 3 ])                       // Create sequence from array

Transforming sequences (intermediate operations):

  • These operations do nothing by themselves, they only start doing work when the terminal operation gets called
  • Function list:

filter map flatMap distinct
take skip takeWhile skipWhile
sort sortAscending sortDescending chunk

  • Examples:
Sequence.range(0, 100);             // Need to create a new sequence with every new pipeline
        .filter(k => k % 2 === 0)   // Keep only even values in the sequence
        .map(k => k * 2)            // Multiply them by 2
        .skip(2)                    // Skip the first 2 elements
        .take(10)                   // Take the first 10 elements only
        .sortAscending()            // Sort them in ascending order

Sequence.from({ prop1: 5, prop2: 'hey' }, { prop1: 5, prop2: 'ho'}, { prop1: 20, prop2: 'hi' })
        .distinct(k => k.prop1)         // Many functions have key selecting overloads, default is always identity
        .sortDescending(k => k.prop1)   // Same happens here

Sequence.from({ data: [ 1, 2, 3, 4 ] }, { data: [ 5, 6, 7, 8 ] })
        .flatMap(k => k.data)
        .takeWhile(k => k < 6)

Finishing sequences (terminal operations):

  • Function list:

forEach reduce toArray toMap partitionBy
sum count average min max
groupBy first last join statistics
allMatches anyMatches

  • Examples
const seq = Sequence.range(0, 100); // Let's assume we recreate this sequence every time

seq.forEach(console.log);           // Print every value to the console
seq.reduce(0, (k, l) => k + l);     // Sum all values
seq.sum();                          // Shorthand for summing
seq.count();                        // Count number of elements in sequence
seq.min();                          // Find the smallest value in the sequence, has key selector overload
seq.max();                          // Find the largest value in the sequence, has key selector overload
seq.average();                      // Average of the values in the sequence
seq.toArray();                      // Collect all elements into an array
seq.first();                        // Find the first element in the sequence, this returns the element or null
seq.last();                         // Find the last element in the sequence, this returns the element or null
seq.join(',');                      // Join elements with a comma
seq.statistics();                   // Returns an object with sum, count, min, max, average properties

const seq = Sequence.from({ prop1: 5, prop2: 'hey' }, { prop1: 20, prop2: 'hi' }, { prop1: 20, prop2: 'hey' });

// Creates an object where the keys are from 'prop1' and the corresponding values are from 'prop2'
// Note: This call throws an error because of the duplicate 'prop1: 20' key
seq.toMap(k => k.prop1, k => k.prop2);

// This is the same as the last example, but this version handles the duplicate key problem by keeping the first value
seq.toMap(k => k.prop1, k => k.prop2, (key, previousValue, currentValue) => previousValue);

// Returns true if the given predicate is true for all elements of the sequence
seq.allMatches(k => k.prop1 > 0);

// Returns true if the given predicate is true for any of the elements of the sequence
seq.anyMatches(k => k.prop2 === 'nope');

// Groups elements by 'prop1' where the values are the objects that had the same key
seq.groupBy(k => k.prop1);

// This does the same as the last example
seq.groupBy(k => k.prop1, Grouper.toArray());

// Groups elements prop1' where the value is the frequency of the key
seq.groupBy(k => k.prop1, Grouper.counting());

// Groups elements by 'prop2' where the value is the sum of 'prop1'
seq.groupBy(k => k.prop2, Grouper.summing(k => k.prop1));

// First array contains the elements where the predicate was true
const [matching, notMatching] = seq.partitionBy(k => k.prop1 % 2 === 0);