Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

js-xiterable

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

js-xiterable

Make ES6 Iterators Functional Again

Source
npmnpm
Version
0.1.2
Version published
Weekly downloads
13
225%
Maintainers
1
Weekly downloads
 
Created
Source

build status

js-xiterable

Make ES6 Iterators Functional Again

Synopsis

Suppose we have a generator like this.

function* count(n) {
    let i = 0;
    while (i < n) yield i++;
};

We make it more functional like this.

import {Xiterable} from './xiterable.js';
const xcount = new Xiterable(n => count(n));
const tens = xcount(10);
const odds = tens.filter(v=>v%2).map(v=>v*v);
const zips = tens.zip(odds);
[...tens];  // [ 0,      1,      2,       3,       4, 5, 6, 7, 8, 9]
[...odds];  // [ 1,      9,     25,      49,      81]
[...zips];  // [[0, 1], [1, 9], [2, 25], [3, 49], [4, 81]]

In other words, this module make any iterables work like Array, with .map, .filter and so on.

Install

npm install js-xiterable

Usage

locally

import {
  Xiterable,
  xiterable,
  zip,
  zipWith,
  xrange,
  repeat
} from './xiterable.js`;

remotely

import {Xiterable} from 'https://cdn.jsdelivr.net/npm/js-xiterable@0.1.2/xiterable.min.js';

commonjs (node.js)

use babel or esm.

% node -r esm
Welcome to Node.js v14.5.0.
Type ".help" for more information.
> import * as _X from './xiterable.js'
undefined
> _X
[Module] {
  Xiterable: [Function: Xiterable],
  isIterable: [Function: isIterable],
  repeat: [Function: repeat],
  xiterable: [Function: xiterable],
  xrange: [Function: xrange],
  zip: [Function: zip],
  zipWith: [Function: zipWith]
}
> [..._X.xrange(10).filter(v=>v%2).map(v=>v*v)]
[ 1, 9, 25, 49, 81 ]
> 

Description

constructor

from any built-in iterables...

new Xiterable([0,1,2,3]);
new Xiterable('0123');
new Xiterable(new Uint8Array([0,1,2,3]))

or your custom generator (with no argument)...

let it = new Xiterable(function *() {
  let i = 0;
  for (;;) yield i++;
});
[...it.take(8)]; // [ 0, 1, 2, 3, 4, 5, 6, 7]

Generators are treated as an infinite iterable. But you can override it by giving its length for the 2nd argument and the implentation of nth for the 3rd argument. see .nth() and .map() for more example.

let it = new Xiterable(function *() {
  let i = 0;
  for (;;) yield i++;
}, Number.POSIVE_INFINITY, n => n);
it.nth(42); // 42
it.take(42).reversed().nth(0) // 41

A factory function is also exported as xiterable.

import {xiterable as $x} from 'js-xiterable';
$x('01234567').zip('abcdefgh').map(v=>v.join('')).toArray(); /* [
  '0a', '1b', '2c', '3d', '4e', '5f', '6g', '7h'
] */

Instance Methods and Properties

.toArray()

Returns [...this].

.nth()

.nth(n) returns the nth element of this if the original itertor has .nth or Array-like (can access nth element via [n]. In which case nth() is auto-generated).

Unlike [n], .nth(n) accepts BigInt and negatives.

let it = xiterable('javascript');
it.nth(0);    // 'j'
it.nth(0n);   // 'j'
it.nth(9);    // 't'
it.nth(-1);   // 't'
it.nth(-1n);  // 't'
it.nth(-10);  // 'j'

It raises exceptions on infinite (and indefinite) iterables

it = xiterable(function*(){ for(;;) yield 42 }); // infinite
[...it.take(42)]; // Array(42).fill(42)
it.nth(0);  // throws TypeError;
it = xiterable('javascript');
it = it.filter(v=>!new Set('aeiou').has(v)); // indefinite
[...it];  // ['j', 'v', 's', 'c', 'r', 'p', 't']
it.nth(0); // throws TypeError;

BigInt is sometimes necessary when you deal with large -- combinatorially large -- iterables like js-combinatorics handles.

import * as $C from 'js-combinatorics';
let it = xiterable(new $C.Permutation('abcdefghijklmnopqrstuvwxyz'));
it = it.map(v=>v.join(''));
it.nth(0);    // 'abcdefghijklmnopqrstuvwxyz'
it.nth(-1);   // 'zyxwvutsrqponmlkjihgfedcba'
it.nth(403291461126605635583999999n) === it.nth(-1);  // true

.length

The (maximum) number of elements in the iterable. For infinite (or indefinite iterables like the result of .filter()) Number.POSITIVE_INFINITY is set.

it = xiterable('javascript');
it.length;  // 10
it = it.filter(v=>!new Set('aeiou').has(v));
it.length;      // Number.POSITIVE_INFINITY
[...it].length; // 7

The number can be BigInt for very large iterable.

it = xiterable(new $C.Permutation('abcdefghijklmnopqrstuvwxyz'));
it.lenth; // 403291461126605635584000000n

You can tell if the iterable is infinite or indefinite via .isEndless.

it = xiterable('javascript');
it.isEndless; // false
it = it.filter(v=>!new Set('aeiou').has(v));
it.isEndless; // true
it = xiterable(new $C.Permutation('abcdefghijklmnopqrstuvwxyz'));
it.isEndless; // false
it = xiterable(function*(){ for(;;) yield 42 }); 
it.isEndless;  // true

.map()

.map(fn, thisArg?) works just like Array.prototype.map except:

  • .map of this module works with infinite iterables.

  • if this is finite with working .nth, the resulting iterable is also reversible with .reversed and random-accissible via .nth.

it = xiterable(function*(){ let i = 0; for(;;) yield i++ });
[...it.map(v=>v*v).take(8)] // [0,  1,  4,  9, 16, 25, 36, 49]
it.nth(42); // throws TypeError
it = xiterable(it.seed, it.length, n=>n); //  installs nth
it.nth(42); // 41

.filter()

.filter(fn, thisArg?) works just like Array.prototype.filter except:

  • .filter of this module works with infinite iterables.

  • unlike .map() the resulting iterable is always marked infinite because there is no way to know its length lazily, that is, prior to iteration. See .length for example

.take()

.take(n) returns an iterator that takes first n elements of this.

.drop()

.drop(n) returns the iterator that drops first n elements of this.

.zip()

.zip(...args) zips iterators in the args. Static version also available.

[...Xiterable.xrange().zip('abcd')]   // [[0,"a"],[1,"b"],[2,"c"],[3,"d"]]

.reversed

returns an iterator that returns elements in reverse order. this must be finite and random-accesible via .nth() or exception is thrown.

instance methods found in Array.prototype

The following methods in Array.prototype are supported as follows. For any method meth, [...iter.meth(arg)] deeply equals to [...iter].meth(arg).

methodavailable?Comment
concat✔︎
copyWithinmutating
entries✔︎
every✔︎
fillmutating ; see repeat
filter✔︎see filter
find✔︎
findIndex✔︎
flat✔︎
flatMap✔︎
forEach✔︎
includes✔︎** throws RangeError on infinite iterables if the 2nd arg is negative
indexOf✔︎** throws RangeError on infinite iterables if the 2nd arg is negative
join✔︎
keys✔︎
lastIndexOf✔︎** throws RangeError on infinite iterables if the 2nd arg is negative
map✔︎see map
popmutating
pushmutating
reduce✔︎** throws RangeError on infinite iterables
reduceRight✔︎** throws RangeError on infinite iterables
reversemutating. See reversed
shiftmutating
slice✔︎** throws RangeError on infinite iterables if any of the args is negative
some✔︎
sortmutating
splicemutating
unshiftmutating
filter✔︎
  • Mutating functions (functions that change this) are deliberately made unavailable. e.g. pop, push

  • Functions that need toiterate backwards do not work on infinite iterables. e.g. lastIndexOf(), reduceRight()

static methods

They are also exported so you can:

import {repeat,xrange,zip,zipWith} from 'xiterable.js'

Examples below assumes

import {Xiterable} from 'xiterable.js'.

Examples below assumes

Xiterable.zip

Zips iterators in the argument.

[...Xiterable.zip('0123', 'abcd')]   // [[0,"a"],[1,"b"],[2,"c"],[3,"d"]]

Xiterable.zipWith

Zips iterators and then feed it to the function.

[...Xiterable.zipWith((a,b)=>a+b, 'bcdfg', 'aeiou')]    // ["ba","ce","di","fo","gu"]

Xiterable.xrange

xrange() as Python 2 (or range() of Python 3).

for (const i of Xiterable.xrange()){ // infinite stream of 0, 1, ...
    console.log(i)
}
[...Xiterable.xrange(4)]        // [0, 1, 2, 3]
[...Xiterable.xrange(1,5)]      // [1, 2, 3, 4]
[...Xiterable.xrange(1,5,2)]    // [1, 3] 

Xiterable.repeat

Returns an iterator with all elements are the same.

for (const i of Xiterable.repeat('spam')) { // infinite stream of 'spam'
    console.log(i)
}
[...Xiterable.repeat('spam', 4)] // ['spam', 'spam', 'spam', 'spam']

Keywords

iterator

FAQs

Package last updated on 31 Jul 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts