iterable-range

3.7.3 • Public • Published

Build Status

iterable-range

The iterable-range module provides iterable range creation functionality with a number of helper methods. Created ranges are lazily evaluated and thus all transforms/modifiers are applied only as needed. Created ranges include the start but not the end values supplied in the parameters

Contents

Installation

npm i --save iterable-range

Usage

range(start, end, step[optional])

Quick creation

import range from 'iterable-range';

const r = range(1, 5);

for (let x of r) {
    console.log(x)  // Prints 1 2 3 4
}

[...r] // [1, 2, 3, 4]

const r2 = range(5) // Single argument, defaults initial value to 0

[...r2] // [0, 1, 2, 3, 4]

Using step parameter

import range from 'iterable-range';

const r = range(1, 10, 2);

[...r]           // [1, 3, 5 ,7, 9]
[...r.reverse()] // [9, 7, 5, 3, 1]

const r2 = range(10, -10, -5);

[...r2]              // [10, 5, 0, -5]
[...r2.reverse()]    // [-5, 0, 5, 10]

Replay-ability

An iterable range can be re-ran an infinite number of times, producing the same values each time. A normal iterator will only be able to be ran once, producing the done for any subsequent runs after the first. A range will just re-run as if it was just initialized.

import range from 'iterable-range';

const r = range(0, 100, 20);
[...r] // [0, 20, 40, 60, 80];
[...r] // [0, 20, 40, 60, 80];
...
...
[...r] // You get the idea

Import using CommonJS

// For commonjs (for now)
const range = require('iterable-range').default
const { concat, zip, distinct } = require('iterable-range');

Methods

Every method applied to an iterable range returns a new iterable range, preserving the original.

const r = range(1, 5);

[...r] // [1, 2, 3, 4]

const r2 = r.map(val => val * -1);

[...r2] // [-1, -2, -3, -4]
[...r] // [1, 2, 3, 4]

map

Parmeters: mapFn - The function to be applied to each viable value in the range.
Mapfn is supplied with just the value to be acted upon

const r = range(1, 5);

[...r.map(val => val * val)] // [1, 4, 9, 16]

// Can have multiple applications

[...r.map(val => val * val).map(val => val % 2 === 0 ? 0 : 1)] // [1, 0, 1, 0]

// Works as expected when a step value is provided
const rWithStep = range(1, 10, 2);

[...rWithStep]                        // [1, 3, 5, 7, 9]
[...rWithStep.map(val => val * val)]  // [1, 9, 25, 49, 81]

filter

Parameters: filterFn - The function to be applied to each vialb value in the range.
If filterFn returns falsy for any given value then that value will not appear in the next chained method, and will effectively be removed from the range. Filterfn is supplied with just the value to be acted upon

const r = range(1, 5);

[...r.filter(val => val % 2)] // [1, 3]

// Can be chained before or after map function

[...r.map(val => val * val).filter(val => val % 2)] // [1, 9]
[...r.filter(val => val % 2).map(val => val * val)] // [1, 9]

limit

Parameters: limitVal - The number of elements to be produced by the range and it's transform chain.
The limit method can appear in any place in the range transform chain, and if multiple calls are made, the last call will be the used value

const r = range(1, Infinity)  // Will run for ever if used without .limit(limitVal)

[...r.limit(5)] // [1, 2, 3, 4, 5]
[...r.limit(5).limit(10)] // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[...r.map(val => val * val).filter(val => val % 2).limit(100)] // Will produce the first 100 odd square numbers

reverse

Reverses the output from the range iterable. It can be called anywhere in the transform chain, but multiple calls will not negate one another -- Once reverse is called output will always be reversed.

const r = range(1, 10);

[...r.reverse()] // [9, 8, 7, 6, 5, 4, 3, 2, 1]

[...r.map(val => val * val).limit(5).reverse()] // [25, 16, 9, 4 ,1]

// if step is provided reverse still returns the exact reverse of the normal output

const rWithStep = range(-20, 42, 7);

[...rWithStep]              // [-20, -13, -6, 1, 8, 15, 22, 29, 36]
[...rWithStep.reverse()]    // [36, 29, 22, 15, 8, 1, -6, -13, -20]

takeUntil

Parameters: takeUntilFn - A function that indicates when the range iterator should stop producing values.

If takeUntilFn returns truthy for any value then the range iterator will disregard that value and stop producing values.

Note No matter where the .takeUntil method is called, it will be applied after all transforms have been applied to any value.

const r = range(1, 10);

[...r.takeUntil(val => val > 6)] // [1, 2, 3, 4, 5, 6]
[...r.takeUntil(val => val === 25).map(val =>  val * val)] // [1, 4, 9, 16]

contains

Parameters: num - Number to check whether it will be produced by the base range iterable.

contains will produce true or false if the given num is going to be produced by the initially created range (the range that has not had any other method applied to it). This is done in constant O(1) time and does not iterate over the produced range, or store anything in another data structure in order to determine if the value will be produced

const r1 = range(10);
r1.contains(3)  // true
r1.contains(10) // false

const r2 = range(-10);
r2.contains(-3)  // true
r2.contains(-10) // false
r2.contains(3)   // false

const r3 = range(-10, 10, 5);
r3.contains(-10)  // true
r3.contains(-8)   // false
r3.contains(0)    // true
r3.contains(10)   // false

length

Returns the number of values that will be produced by the base range iterable. Calling length will return the number of items that will be produced. This is done in constant O(1) time and does not iterate over the values, or store them in another data structure to determine the length

const r1 = range(1, 10);
r1.length()  // 9

const r2 = range(10);
r2.length()  // 10

const r3 = range(1, 20, 2);
r3.length()  // 10

const r4 = range(-10, -32, -3);
r4.length()  // 8

const r5 = range(1, Infinity);
r5.length()  // Infinity

Operators

Operators are added utility methods that may or may not be restricted to usage with iterable ranges.

combine

Parameters: iters - Array of iterables
Parameters: combineFn - function that maps from an array of values, to some other value(s)
Throws: TypeError - if iters is not an array
Throws: TypeError - if any element in iters is not an iterable

combine takes an array of iterables and produces a new iterable that combines the values from each iterable, either as an array of each value from each iterable, or as a new value that has been mapped by the given combineFn. The values that are stored in the returned array represent the value that is produced by each given iterable at that position in its iterator.

The given combineFn will be passed the array of combined values, and can return any output that it desires.

const iter1 = [1, 2, 3];
const iter2 = [4, 5, 6];

const iters = [iter1, iter2];

[...combine(iters)] // [[1, 4], [2, 5], [3, 6]]

const sum = values => values.reduce((result, value) => result + value, 0);

[...combine(iters, sum)] // [5, 7, 9];

concat

Parameters: ...Iterable(s) - Any number of iterables.
Throws: TypeError - If any given argument is not an iterable.

concat returns an iterable that will produce values from each iterator. The values produced will be from only one iterable at a time, until it has been exhausted. The ordering will be in the same order that the iterables are provided

import range, { concat } from 'iterable-range';

const r1 = range(0, 10, 2);
const r2 = range(8, -1, -2);

[...concat(r1, r2)]  // [0, 2, 4, 6, 8, 8, 6, 4, 2, 0]


const iter1 = 'hello ';
const iter2 = 'world';

[...concat(iter1, iter2)] // ['h', 'e', 'l', 'l'. 'o', ' ', 'w', 'o', 'r', 'l', 'd'];

zip

Parameters: ...Iterable(s) - Any number of iterable(s).
Throws: TypeError - If any given argument is not an iterable.

zip returns an iterable that will produce the interleaved values of the provided iterables. It will produce its values from the iterables in the order that they are passed into the function. It will continue to produce values until all given iterables have exhausted there values.

Note The iterable returned by the zip function will only produce values one time. Any subsequent call after the initial call will return { done: true } Note Any iterables passed in that are not replay-able will also be exhausted

import range, { zip } from 'iterable-range';

const r1 = range(1, 10, 2);
const r2 = range(1, 20, 4);

[...zip(r1, r2)] // [1, 1, 3, 5, 5, 9, 7, 13, 9, 17]

const i1 = [1, 2, 3, 4];
const i2 = [4, 3, 2, 1];

[...zip(i1, i2)] // [1, 4, 2, 3, 3, 2, 4, 1];

const i3 = [1, 2, 3, 4, 6, 6, 6];

[...zip(i3, i2)] // [1, 4, 2, 3, 3, 2, 4, 1, 6, 6, 6];

distinct

Parameters: Iterable - Any item that implements the iterable protocol
Throws: TypeError - If parameter does not implement the iterable protocol

distinct returns an iterable that will produce only unique values. Any duplicates found in the given iterable will only be returned once, all others will be discarded.

Note distinct will exhaust any non-replayable iterable that is operated on.
Note distinct uses a Set internally and could potentially use memory-space O(m) (m = total number of produced values)

import range, { zip, distinct } from 'iterable-range';

const r1 = range(1, 20, 2);
const r2 = range(1, 20, 4);
const z = zip(r1, r2);

[...distinct(z)] // [1, 3, 5, 9, 7, 13, 17, 11, 15, 19]

[...distinct('Hello World!')] // ['H', 'e', 'l', 'o', ' ', 'W', 'r', 'd', '!']

Package Sidebar

Install

npm i iterable-range

Weekly Downloads

0

Version

3.7.3

License

ISC

Unpacked Size

46.5 kB

Total Files

14

Last publish

Collaborators

  • hillc5