A small (~600B gzip), useful set of methods for lazy iteration of iterables.

Overview

@ricokahler/lazy Β· codecov github status checks bundlephobia semantic-release

A small (~600B gzip*), useful set of methods for lazy iteration of iterables.



Why this lazy lib?

  1. Small size (~600B gzipped)
  2. Simple, modern for...of-only implementations. (Read the source here)
  3. Only ships useful* methods

*Useful is a keyword here because this library only ships with iterable methods that can take advantage of chained lazy iteration.

What that boils down to is shipping methods that never have to exhaust the iterable in order to yield the next item.

An example of this would be a reverse() method. If this lib implemented a reverse() method, it would have to buffer the items received from the iterable into an array to be able to yield the items in reverse.

Since we have to buffer the items into an array anyway, there's not all that much difference between:

Lazy.from(iterable).reverse(); // not implemented!

and

Lazy.from(iterable).to(Array).reverse();

This constraint has some mental model benefits too. If you find yourself frequently needing to convert your iterable to an array, then there's a good chance lazy evaluation is not giving you much benefit.

Do I even need a lazy lib?

In order to take full advantage of the short-circuiting nature of call-by-need/lazy-evaluation, your Lazy expression should either:

  1. terminate in short-circuiting method
  2. take (via take or takeWhile) a subset of the iterable

Installation

npm i @ricokahler/lazy

Usage

Both ESM and CJS are supported in this package.

// esm
import Lazy from '@ricokahler/lazy';
// common-js
const Lazy = require('@ricokahler/lazy');

You can then:

  1. chain the methods like arrays:
const result = Lazy.from([1, 2, 3])
  .map((x) => x + 1)
  .filter((x) => x >= 3)
  .first();

console.log(result); // 3
  1. Or use the static method counterparts:
let iterable = Lazy.from([1, 2, 3]);
iterable = Lazy.map(iterable, (x) => x + 1);
iterable = Lazy.filter(iterable, (x) => x >= 3);
const result = Lazy.first(iterable);

console.log(result); // 3

Method Reference

Conversion methods

Chainable methods

Short-circuiting, terminating methods

Conversion methods

Lazy.from | πŸ”

Takes in any iterable and returns it wrapped in a Lazy with chainable Lazy methods.

// static method only
Lazy.from<T>(iterable: Iterable<T>): Lazy<T>

Note: this is equivalent to calling new Lazy(iterable)

to | πŸ”

Writes the iterable into another data structure. Accepts an object with a from method that accepts an iterable (e.g. Array.from) or a constructor that accepts an iterable.

The implementation is as follows:

function to(iterable, constructorOrFromable) {
  if (typeof constructorOrFromable.from === 'function') {
    return constructorOrFromable.from(iterable);
  }
  return new constructorOrFromable(iterable);
}
Lazy<T>.to<TInstance>(fromable: {from: (iterable: Iterable<T>) => TInstance}): TInstance
Lazy<T>.to<TInstance>(constructor: {new (iterable: Iterable<T>) => TInstance}): TInstance

Chainable methods

map | πŸ”

Takes in an iterable and returns an iterable generator that yields the result of the callback function on each item from the input iterable.

Lazy<T>.map<R>(mapper: (t: T) => R): Lazy<R>

filter | πŸ”

Takes in an iterable and returns an iterable generator that yields the accepted elements of the given callback function.

Lazy<T>.filter<R extends T>(accept: (t: T) => t is R): Lazy<R>
Lazy<T>.filter<R extends T>(accept: (t: T) => t is R): Lazy<R>

flat | πŸ”

Returns a new iterable with all sub-iterable items yielded into it recursively up to the specified depth.

Lazy<T>.flat<TDepth extends number>(depth?: TDepth): Lazy<Flattened<T, TDepth>>

flatMap | πŸ”

Calls the result of the given callback function on each item of the parent iterable. Then, yields the result of each into a flatted iterable. This is identical to a map followed by flat with depth 1.

Lazy<T>.flatMap<R>(mapper: (value: T) => R | Iterable<R>): Lazy<R>

take | πŸ”

Yields the first n items of the given iterable and stops further iteration.

const result = Lazy.from([1, 2, 3, 4, 5]).take(3).to(Array);

console.log(result); // [1, 2, 3]
Lazy<T>.take(n: number): Lazy<T>

takeWhile | πŸ”

Yields while the callback function accepts the current item from the given iterable. Iteration finishes as soon as an item is rejected by the callback.

const result = Lazy.from([1, 2, 3, 4, 5, 0, 1])
  .takeWhile((n) => n <= 2)
  .to(Array);
console.log(result); // [1, 2]
Lazy<T>.takeWhile<R extends T>(accept: (t: T) => t is R): Lazy<R>
Lazy<T>.takeWhile(accept: (t: T) => unknown): Lazy<T>

skip | πŸ”

Skips over the first n items of the given iterable then yields the rest.

const result = Lazy.from([1, 2, 3, 4, 5]).skip(2).to(Array);
console.log(result); // [3, 4, 5]
Lazy<T>.skip(n: number): Lazy<T>

skipWhile | πŸ”

Skips over the items while the given callback accepts the current item from the given iterable, then yields the rest.

const result = Lazy.from([1, 2, 3, 4, 5, 0, 1])
  .skipWhile((n) => n <= 2)
  .to(Array);

console.log(result); // [3, 4, 5, 0, 1]
Lazy<T>.skip(n: number): Lazy<T>

Short-circuiting, terminating methods

includes | πŸ”

Determines whether an iterable includes a certain value using === comparison. Short-circuits iteration once the value is found.

Lazy<T>.includes(t: T): boolean

first | πŸ”

Returns the first item of an iterable or undefined if the iterable is done/exhausted.

Lazy<T>.first(): T | undefined

find | πŸ”

Returns the first item accepted by the given callback. Short-circuits iteration once an item is found.

Lazy<T>.find<R extends T>(accept: (t: T) => t is R): R | undefined
Lazy<T>.find(accept: (t: T) => unknown): T | undefined

some | πŸ”

Returns true if at least one item accepted by the given callback. Short-circuits iteration once an item is accepted.

Lazy<T>.some(accept: (t: T) => unknown): boolean

every | πŸ”

Returns true only if all items are accepted by the given callback. Short-circuits iteration once an item is rejected.

Lazy<T>.every(accept: (t: T) => unknown): boolean
Comments
Releases(v2.0.2)
Owner
Rico Kahler
Sanity.io Software Engineer in Detroit | previously at Bloomscape
Rico Kahler
Fast and lightweight dependency-free vanilla JavaScript polyfill for native lazy loading / the awesome loading='lazy'-attribute.

loading="lazy" attribute polyfill Fast and lightweight vanilla JavaScript polyfill for native lazy loading, meaning the behaviour to load elements rig

Maximilian Franzke 571 Dec 30, 2022
A workshop about JavaScript iteration protocols: iterator, iterable, async iterator, async iterable

JavaScript Iteration protocol workshop A workshop about JavaScript iteration protocols: iterator, iterable, async iterator, async iterable by @loige.

Luciano Mammino 96 Dec 20, 2022
Grupprojekt fΓΆr kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet fΓΆr kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide FΓΆr information om hur utv

Svante Jonsson IT-HΓΆgskolan 3 May 18, 2022
Hemsida fΓΆr personer i Sverige som kan och vill erbjuda boende till mΓ€nniskor pΓ₯ flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo fΓΆr kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Well-tested utility functions dealing with async iterables

aitertools This library provides a well-tested collection of small utility functions dealing with async iterables. You can think of it as LINQ or aite

Hong Minhee (ζ΄ͺ 民憙) 11 Aug 15, 2022
Iterables, streams for typescript

Iterable for Typescript Similar to what we know from C#, Dart or any other language which supports them, we use Iterables to stream over collections.

null 3 Oct 15, 2022
Provides simple and the most useful methods to string operations in JavaScript / Node.js

?? Strops (String Operations) Provides simple methods for the most useful operations with substrings: - remove, replace, get from A to B, get from A t

Max Shane 3 May 20, 2022
Create your own wrappings with optional key bindings for selected text, a set of useful defaults is also provided.

Create your own wrappings with optional key bindings for selected text, a set of useful defaults is also provided.

Seth Yuan 66 Jan 1, 2023
This is a repo for small, useful scripts and extensions

WinDbgCookbook This is a repo for small, useful scripts, extensions, and debugger data model "dx" queries. Feel free to add your own scripts or update

Tim Misiak 170 Dec 19, 2022
To Do list is a small but useful project to make list app , you can add tasks delete tasks and modify tasks, the project built using HTML, CSS, JavaScript

Project Name The To-Do-List app description this is a project in the second week of the second module in microverse. its a useful to do list that save

Alzubair Alqaraghuli 5 Jul 25, 2022
SET Revision is a website to help you identify "sets" in the card game SET.

Welcome to SET Revision! SET Revision is a website to help you identify "sets" in the card game SET. The code in this repository is aimed for learners

Benjamin Piper 2 Oct 3, 2022
A set of small, responsive CSS modules that you can use in every web project.

Pure A set of small, responsive CSS modules that you can use in every web project. https://purecss.io/ This project is looking for maintainers to supp

Pure CSS 22.7k Jan 9, 2023
A small javascript DOM manipulation library based on Jquery's syntax. Acts as a small utility library with the most common functions.

Quantdom JS Quantdom is a very small (about 600 bytes when ran through terser & gzipped) dom danipulation library that uuses a Jquery like syntax and

Sean McQuaid 7 Aug 16, 2022
✏️ A small jQuery extension to turn a static HTML table into an editable one. For quickly populating a small table with JSON data, letting the user modify it with validation, and then getting JSON data back out.

jquery-editable-table A small jQuery extension to turn an HTML table editable for fast data entry and validation Demo ?? https://jsfiddle.net/torrobin

Tor 7 Jul 31, 2022
JSPro is nothing but JavaScript Prototypes! The publisher is too lazy to write full name that's why it's just JSPro.

JSPro is nothing but JavaScript Prototypes! The publisher is too lazy to write full name that's why it's just JSPro. Whatever, it's a library of hundreds of awesome JavaScript Prototypes (you may know it as dot function) for lazy programmers. Just install the package with a little effort and leave the blames for the publisher.

Jafran Hasan 2 Mar 10, 2022
Fancytree - JavaScript tree view / tree grid plugin with support for keyboard, inline editing, filtering, checkboxes, drag'n'drop, and lazy loading

Fancytree Fancytree (sequel of DynaTree 1.x) is a JavaScript tree view / tree grid plugin with support for keyboard, inline editing, filtering, checkb

Martin Wendt 2.6k Jan 9, 2023
A lazy plugin for printing local network when starting NodeJS server. I made this so you don't have to.

lazy-net A simple, lightweight plugin for printing local network when starting Node.js or Express.js server. I made this so you don't have to. There a

TrαΊ§n Quang Kha (始) 1 Feb 10, 2022