SkillAgentSearch skills...

Itiriri

A library built for ES6 iteration protocol.

Install / Use

/learn @labs42io/Itiriri
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

itiriri

Build Status Coverage Status NPM Version license

A library built for ES6 iteration protocol.

function* numbers() {
  let n = 1;

  while (true) {
    yield n++;
  }
}

const s = itiriri(numbers()).map(n => 1 / (n * n)).take(1000).sum();
console.log(Math.sqrt(6 * s));
// 3.1406380562059946

itiriri provides similar functions as JavaScript arrays: filter, slice, map, reduce, every, some etc. and more. The functions are optimized for ES6 iterators and can be chained to perform simple but powerful manipulations over iterables.

Installation

Using npm

$ npm install 'itiriri' --save

Importing

import itiriri from 'itiriri';

Support

The itiriri library can be used with any ES6 compatible runtime.

Usage

itiriri can be used with a build-it type like array, Map, Set, a generator function or a custom iterable.

import itiriri from 'itiriri';

const values = [2, 0, 4, 8];

const s = itiriri(values).map(n => n / 2).reverse();
console.log(s.toString()); // prints: 4,2,0,1

// prints: 4 2 0 1
for (const n of s) {
  console.log(n)
}

console.log(s.sum()); // prints: 7

Deferred execution

JavaScript's array methods like filter, slice and others that return an array create a shallow copy for the result and are executed once called.

itiriri functions that return iterables are not executed unless chained with a function that reduces a value or transforms to a built-in type. The iterable source is iterated only once.

Let's see what happens in the below example.

import itiriri from 'itiriri';

function* fibonacci() {
  let [a, b] = [0, 1];

  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

// Finding first 3 Fibonacci numbers that contain 42
const result = itiriri(fibonacci())
  .filter(x => x.toString().indexOf('42') !== -1)
  .take(3);

for (const e of result) {
  console.log(e);
}

// outputs: 514229, 267914296, 7778742049

Step by step:

  1. result is assigned to a itiriri. At this point numbers array is not iterated, the execution is deferred until the result is being iterated.

  2. filter method creates an iterator to pipe only numbers passing the predicate. filter does not buffer elements and only pipes them one-by-one to take as it is iterated.

  3. take pipes only first three elements as it is iterated and breaks.

  4. for...of instruction starts iteration and requests elements one at a time.

Due to deferred execution, most of the functions that don't need entire sequence of elements to build an iterator (like filter, map, concat etc.) can be used with infinite iterables (like Fibonacci in the above example). These functions are also optimized to pass elements through and do not buffer them resulting in a more optimized memory usage.

Functions like sort, reverse, shuffle etc. that require entire sequence of elements in order to build an iterator expect to receive a finite iterable.

Benchmarks

Using itiriri is considerable faster than using array methods when processing large inputs.

In filter-map-slice example arrays of different size are used to filter and map a result of 100 elements:

|Array size (N) | array | itiriri | |---------------|------------------------------------|-----------------------------------| |1000 |111,611 ops/sec ±9.63% (86 runs) | 44,213 ops/sec ±1.92% (88 runs) | |5000 |18,507 ops/sec ±0.67% (90 runs) | 42,103 ops/sec ±2.63% (84 runs) | |10000 |8,655 ops/sec ±0.70% (91 runs) | 42,803 ops/sec ±2.20% (86 runs) | |50000 |1,640 ops/sec ±0.79% (88 runs) | 43,446 ops/sec ±2.17% (88 runs) | |100000 |848 ops/sec ±0.93% (87 runs) | 43,137 ops/sec ±2.15% (87 runs) | |200000 |46.38 ops/sec ±0.74% (59 runs) | 42,445 ops/sec ±2.48% (90 runs) |

map-filter-slice

Using array methods performance drops significantly for large inputs due to creation of intermediary states for filter and map.
Using itiriri iteration always stops after 100 elements are found, therefore the size of the input doesn't affect the performance.

More benchmarks can be found in /benchmark.

Running Tests

$ npm install
$ npm test

Bundling

If you want to use itiriri in the browser, there is a gulp task that creates a minified file:

$ npm install
$ gulp bundle
// creates itiriri.min.js file in the root folder

Once you include the itiriri.min.js file on your page, you can use it as:

<script src="itiriri.min.js"></script>
<!-- ... -->
<script>
    // source can be an array or an Iterable
    const source = [1, 2, 3];
    console.log(itiriri(source).sum());
</script>

Complete list of methods

average

Returns the average value.

Syntax

average(): number;
average(selector: (element: T, index: number) => number): number;

Parameters

  • selector - (optional) a value transformer that accepts two arguments:
    • element - the current element
    • index - the index of the current element
    • returns a number that is used for average value calculation

For a sequence with no elements returns undefined.

Example

import itiriri from 'itiriri';

itiriri([41, 42, 43]).average()  // returns 42
itiriri([{value: 1}, {value: 2}]).average(elem => elem.value) // returns 1.5
itiriri([]).average() // returns undefined

concat

Concatenates a sequence with another one.

Syntax

concat(other: Iterable<T>): IterableQuery<T>;
concat(other: T): IterableQuery<T>;

Parameters

  • other - (required) a sequence or a value to be concatenated

Example

import itiriri from 'itiriri';

itiriri([1, 2, 3]).concat([4, 5]).toArray()  // returns [1, 2, 3, 4, 5]

concat is a deferred method and is executed only when the result sequence is iterated.

distinct

Returns a sequence of unique elements.

Syntax

distinct(): IterableQuery<T>;
distinct<S>(selector: (element: T) => S): IterableQuery<T>;

Parameters

  • selector - (optional) a function to get element's value for comparison. Accepts one argument:
    • element - current element
    • returns a value to be used for comparison

Example

import itiriri from 'itiriri';

itiriri([1, 42, 3, 4, 1]).distinct().toArray();  // returns [1, 42, 3, 4]
itiriri([{value: 1}, {value: 2}, {value: 1}])
  .distinct(elem => elem.value)
  .toArray(); // returns [{value: 1}, {value: 2}]

distinct is a deferred method and is executed only when the result sequence is iterated.

entries

Returns a sequence of key/value pair for each element and its index.

Syntax

entries(): IterableQuery<[number, T]>;

Example

import itiriri from 'itiriri';

itiriri(['Alice', 'Bob', 'David']).entries().toArray();
// returns [[0, 'Alice'], [1, 'Bob'], [2, 'David']]

entries is a deferred method and is executed only when the result sequence is iterated.

every

Tests whether all the elements pass the predicate.

Syntax

every(predicate: (element: T, index: number) => boolean): boolean;

Parameters

  • predicate - (required) function to test for each element
    • element - the current element
    • index - the index of the current element
    • returns true or false

Example

import itiriri from 'itiriri';

itiriri([2, 4, 9]).every(elem => elem > 0); // returns true
itiriri([7, 23, 3]).every(elem => elem % 3 === 0); // returns false

exclude

Returns a sequence of elements not contained in a given sequence.

Syntax

exclude<S>(others: Iterable<T>): IterableQuery<T>;
exclude<S>(others: Iterable<T>, selector: (element: T) => S): IterableQuery<T>;

Parameters

  • others - (required) a sequence of elements to be excluded
  • selector - (optional) a function to get element's value for comparison, accepts one argument:
    • element - current element
    • returns a value to be used for comparison

Example

import itiriri from 'itiriri';

itiriri([2, 0,

Related Skills

View on GitHub
GitHub Stars180
CategoryDevelopment
Updated8mo ago
Forks8

Languages

TypeScript

Security Score

92/100

Audited on Aug 1, 2025

No findings