Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@thi.ng/transducers

Package Overview
Dependencies
Maintainers
1
Versions
331
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@thi.ng/transducers - npm Package Compare versions

Comparing version 0.11.2 to 1.0.0

CHANGELOG.md

10

index.d.ts

@@ -12,2 +12,3 @@ export * from "./api";

export * from "./rfn/count";
export * from "./rfn/every";
export * from "./rfn/frequencies";

@@ -17,3 +18,2 @@ export * from "./rfn/group-binary";

export * from "./rfn/group-by-obj";
export * from "./rfn/join";
export * from "./rfn/last";

@@ -29,2 +29,4 @@ export * from "./rfn/max-compare";

export * from "./rfn/reductions";
export * from "./rfn/some";
export * from "./rfn/str";
export * from "./xform/base64";

@@ -50,2 +52,3 @@ export * from "./xform/benchmark";

export * from "./xform/keep";
export * from "./xform/labeled";
export * from "./xform/map-indexed";

@@ -57,2 +60,5 @@ export * from "./xform/map-keys";

export * from "./xform/moving-average";
export * from "./xform/multiplex";
export * from "./xform/multiplex-obj";
export * from "./xform/noop";
export * from "./xform/pad-last";

@@ -78,2 +84,4 @@ export * from "./xform/partition-by";

export * from "./xform/throttle";
export * from "./xform/throttle-time";
export * from "./xform/utf8";
export * from "./func/binary-search";

@@ -80,0 +88,0 @@ export * from "./func/comp";

@@ -17,2 +17,3 @@ "use strict";

__export(require("./rfn/count"));
__export(require("./rfn/every"));
__export(require("./rfn/frequencies"));

@@ -22,3 +23,2 @@ __export(require("./rfn/group-binary"));

__export(require("./rfn/group-by-obj"));
__export(require("./rfn/join"));
__export(require("./rfn/last"));

@@ -34,2 +34,4 @@ __export(require("./rfn/max-compare"));

__export(require("./rfn/reductions"));
__export(require("./rfn/some"));
__export(require("./rfn/str"));
__export(require("./xform/base64"));

@@ -55,2 +57,3 @@ __export(require("./xform/benchmark"));

__export(require("./xform/keep"));
__export(require("./xform/labeled"));
__export(require("./xform/map-indexed"));

@@ -62,2 +65,5 @@ __export(require("./xform/map-keys"));

__export(require("./xform/moving-average"));
__export(require("./xform/multiplex"));
__export(require("./xform/multiplex-obj"));
__export(require("./xform/noop"));
__export(require("./xform/pad-last"));

@@ -83,2 +89,4 @@ __export(require("./xform/partition-by"));

__export(require("./xform/throttle"));
__export(require("./xform/throttle-time"));
__export(require("./xform/utf8"));
__export(require("./func/binary-search"));

@@ -85,0 +93,0 @@ __export(require("./func/comp"));

2

iter/reverse.d.ts

@@ -10,2 +10,2 @@ /**

*/
export declare function reverse<T>(input: Iterable<T>): IterableIterator<any>;
export declare function reverse<T>(input: Iterable<T>): IterableIterator<T>;
{
"name": "@thi.ng/transducers",
"version": "0.11.2",
"version": "1.0.0",
"description": "Lightweight transducer implementations for ES6 / TypeScript",
"main": "./index.js",
"typings": "./index.d.ts",
"repository": "https://github.com/thi-ng/transducers",
"repository": "https://github.com/thi-ng/umbrella",
"author": "Karsten Schmidt <k+npm@thi.ng>",

@@ -14,3 +14,3 @@ "license": "Apache-2.0",

"clean": "rm -rf *.js *.d.ts build doc func iter rfn xform",
"pub": "yarn run build && (cd build && yarn publish --access public)"
"pub": "yarn run build && yarn publish --access public"
},

@@ -27,4 +27,3 @@ "devDependencies": {

"dependencies": {
"@thi.ng/api": "^1.2.1",
"@thi.ng/checks": "^1.1.1"
"@thi.ng/api": "^1.3.0"
},

@@ -31,0 +30,0 @@ "keywords": [

@@ -21,4 +21,4 @@ # @thi.ng/transducers

Currently, the library provides altogether 75+ transducers, reducers and
sequence generators for composing data transformation pipelines.
This library provides altogether ~85 transducers, reducers and sequence
generators (iterators) for composing data transformation pipelines.

@@ -28,16 +28,16 @@ The overall concept and many of the core functions offered here are directly

implementation does differ (also in contrast to some other JS based
implementations) and several less common, but generally highly useful operators
implementations) and dozens of less common, but generally highly useful operators
have been added, with at least a couple dozen more to come.
Please see the [@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators) &
[@thi.ng/csp](https://github.com/thi-ng/umbrella/tree/master/packages/csp) partner modules for related
functionality, supplementing features of this library. However, this lib has no
dependencies on either of them. The only dependency is
[@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) for re-using common types &
interfaces.
Please see the
[@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/master/packages/rstream)
& [@thi.ng/csp](https://github.com/thi-ng/umbrella/tree/master/packages/csp)
partner modules for related functionality, supplementing features of this
library and depending on it.
Having said this, since 0.8.0 this project largely supersedes the
[@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators) library for most use
cases and offers are more powerful API and potentially faster execution of
composed transformations (due to lack of ES generator overheads).
Since 0.8.0 this project largely supersedes the
[@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators)
library for most use cases and offers are more powerful API and potentially
faster execution of composed transformations (due to lack of ES generator
overheads).

@@ -89,4 +89,4 @@ ## Installation

// single step execution
// (currently doesn't work w/ mapcat(), duplicate() and some others)
// returns undefined if transducer returned no result for this input
// returns array if transducer step produced multiple results
f = tx.step(xform);

@@ -97,10 +97,7 @@ f(1) // 3

f(4) // undefined
f(5) // 15
f(4) // undefined
f(3) // undefined
f(2) // undefined
f(1) // undefined
f = tx.step(take)
```
### Histogram generation
### Histogram generation & result grouping

@@ -116,4 +113,56 @@ ```typescript

// Map { 1 => 3, 2 => 1, 3 => 1, 4 => 2 }
// with optional key function, here to bin by word length
tx.reduce(
tx.frequencies(x => x.length),
"my camel is collapsing and needs some water".split(" ")
)
// Map { 2 => 2, 5 => 3, 10 => 1, 3 => 1, 4 => 1 }
// actual grouping
tx.reduce(
tx.groupByMap(x => x.length),
"my camel is collapsing and needs some water".split(" ")
)
// Map {
// 2 => [ 'my', 'is' ],
// 3 => [ 'and' ],
// 4 => [ 'some' ],
// 5 => [ 'camel', 'needs', 'water' ],
// 10 => [ 'collapsing' ]
// }
```
### Multiplexing / parallel transducer application
`multiplex` and `multiplexObj` can be used to transform values in parallel
using the provided transducers (which can be composed as usual) and results in
a tuple or keyed object.
```typescript
tx.transduce(
tx.multiplex(
tx.map(x => x.charAt(0)),
tx.map(x => x.toUpperCase()),
tx.map(x => x.length)
),
tx.push(),
["Alice", "Bob", "Charlie"]
)
// [ [ "A", "ALICE", 5 ], [ "B", "BOB", 3 ], [ "C", "CHARLIE", 7 ] ]
tx.transduce(
tx.multiplexObj({
initial: tx.map(x => x.charAt(0)),
name: tx.map(x => x.toUpperCase()),
len: tx.map(x => x.length)
}),
tx.push(),
["Alice", "Bob", "Charlie"]
)
// [ { len: 5, name: 'ALICE', initial: 'A' },
// { len: 3, name: 'BOB', initial: 'B' },
// { len: 7, name: 'CHARLIE', initial: 'C' } ]
```
### Moving average using sliding window

@@ -123,4 +172,2 @@

// use nested reduce to compute window averages
// this combined transducer is also directly
// available as: `tx.movingAverage(n)`
tx.transduce(

@@ -135,2 +182,10 @@ tx.comp(

// [ 2.6, 3.4, 4, 4.6, 5.4, 6.2, 6.8, 7.6, 8.4 ]
// this combined transducer is also directly
// available as: `tx.movingAverage(n)`
tx.transduce(
tx.movingAverage(5),
[1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 9, 10]
);
// [ 2.6, 3.4, 4, 4.6, 5.4, 6.2, 6.8, 7.6, 8.4 ]
```

@@ -182,3 +237,3 @@

The `struct` transducer is simply a composition of: `partitionOf -> partition -> rename -> mapKeys`.
[See code here](https://github.com/thi-ng/transducers/blob/master/src/xform/struct.ts).
[See code here](https://github.com/thi-ng/umbrella/tree/master/packages/transducers/src/xform/struct.ts).

@@ -266,3 +321,3 @@ ```typescript

This is a higher-order transducer, purely composed from other transducers.
[See code here](https://github.com/thi-ng/transducers/blob/master/src/xform/hex-dump.ts).
[See code here](https://github.com/thi-ng/umbrella/tree/master/packages/transducers/src/xform/hex-dump.ts).

@@ -302,3 +357,3 @@ ```typescript

### Base64 en/decoding
### Base64 & UTF-8 en/decoding

@@ -313,3 +368,3 @@ ```typescript

),
tx.join(),
tx.str(),
tx.range(-8, 8)

@@ -328,2 +383,12 @@ );

// [ -8, -7, -6, -5, -4, -3, -2, -1 ]
buf = tx.transduce(
tx.comp(tx.utf8Encode(), tx.base64Encode()),
tx.str(),
"beer (🍺) or hot beverage (☕︎)"
);
// "YmVlciAo8J+Nuikgb3IgaG90IGJldmVyYWdlICjimJXvuI4p"
tx.transduce(tx.comp(tx.base64Decode(), tx.utf8Decode()), tx.str(), buf)
// "beer (🍺) or hot beverage (☕︎)"
```

@@ -344,4 +409,4 @@

_Documentation is slowly forthcoming in the form of doc comments (incl. code
examples) for a small, but growing number the functions listed below. Please
see source code for now._
examples) for a growing number the functions listed below. Please see source
code for now._

@@ -392,4 +457,4 @@ ### Types

Currently `partition`, `partitionBy`, `streamSort`, `streamShuffle` are the only operators making
use of the 1-arity completing function of their reducer.
`partition`, `partitionBy`, `streamSort`, `streamShuffle` are (examples of)
transducers making use of their 1-arity completing function.

@@ -471,7 +536,8 @@ #### Reduced

Helper function to build reducers.
Helper function to compose reducers.
#### `iterator<A, B>(tx: Transducer<A, B>, xs: Iterable<A>): IterableIterator<B>`
Similar to `transduce()`, but emits results as ES6 iterator (and hence doesn't use a reduction function).
Similar to `transduce()`, but emits results as ES6 iterator (and hence doesn't
use a reduction function).

@@ -531,2 +597,4 @@ #### `reduce<A, B>(rfn: Reducer<A, B>, acc: A, xs: Iterable<B>): A`

#### `labeled<L, T>(id: L): Transducer<T, [L, T]>`
#### `map<A, B>(fn: (x: A) => B): Transducer<A, B>`

@@ -544,2 +612,8 @@

#### `multiplex<T, A, B>(a: Transducer<T, A>, b: Transducer<T, B>...): Transducer<T, [A, B...]>`
#### `multiplexObj<A, B>(xforms: IObjectOf<Transducer<A, any>>, rfn?: Reducer<B, [PropertyKey, any]>): Transducer<A, B>`
#### `noop<T>(): Transducer<T, T>`
#### `padLast<T>(n: number, fill: T): Transducer<T, T>`

@@ -585,2 +659,8 @@

#### `throttleTime<T>(delay: number): Transducer<T, T>`
#### `utf8Decode(): Transducer<number, string>`
#### `utf8Encode(): Transducer<string, number>`
### Reducers

@@ -598,4 +678,6 @@

#### `frequencies<T>(): Reducer<Map<T, number>, T>`
#### `every<T>(pred?: Predicate<T>): Reducer<boolean, T>`
#### `frequencies<A, B>(key: (x: A) => B): Reducer<Map<B, number>, A>`
#### `groupBinary<T>(bits: number, key: (x: T) => number, branch?: () => IObjectOf<T[]>, leaf?: Reducer<any, T>, left?: PropertyKey, right?: PropertyKey): Reducer<any, T>`

@@ -625,2 +707,6 @@

#### `reductions<A, B>(rfn: Reducer<A, B>): Reducer<A[], B>`
#### `some<T>(pred?: Predicate<T>): Reducer<boolean, T>`
### Generators / Iterators

@@ -627,0 +713,0 @@

import { Reducer } from "../api";
export declare function frequencies<T>(): Reducer<Map<T, number>, T>;
export declare function frequencies<A, B>(key?: ((x: A) => B)): Reducer<Map<B, number>, A>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function frequencies() {
return [
() => new Map(),
(acc) => acc,
(acc, x) => acc.set(x, acc.has(x) ? acc.get(x) + 1 : 1)
];
const identity_1 = require("../func/identity");
const count_1 = require("./count");
const group_by_map_1 = require("./group-by-map");
function frequencies(key = identity_1.identity) {
return group_by_map_1.groupByMap(key, count_1.count());
}
exports.frequencies = frequencies;
import { IObjectOf } from "@thi.ng/api/api";
import { Reducer } from "../api";
/**
* Creates a bottom-up binary tree of desired depth and choice of
* data structures. Any value can be indexed, as long as a numeric
* representation (key) can be obtained. This mapping is produced
* Creates a bottom-up, unbalanced binary tree of desired depth and
* choice of data structures. Any value can be indexed, as long as a
* numeric representation (key) can be obtained. This mapping is produced
* by the supplied `key` function. IMPORTANT: the returned values

@@ -8,0 +8,0 @@ * MUST be unsigned and less than the provided bit length (i.e. 2^`bits`).

@@ -9,5 +9,5 @@ "use strict";

/**
* Creates a bottom-up binary tree of desired depth and choice of
* data structures. Any value can be indexed, as long as a numeric
* representation (key) can be obtained. This mapping is produced
* Creates a bottom-up, unbalanced binary tree of desired depth and
* choice of data structures. Any value can be indexed, as long as a
* numeric representation (key) can be obtained. This mapping is produced
* by the supplied `key` function. IMPORTANT: the returned values

@@ -14,0 +14,0 @@ * MUST be unsigned and less than the provided bit length (i.e. 2^`bits`).

import { Reducer } from "../api";
export declare function groupByMap<A, B, C>(key: (x: A) => B, rfn?: Reducer<C, A>): Reducer<Map<B, C>, A>;
export declare function groupByMap<A, B, C>(key?: ((x: A) => B), rfn?: Reducer<C, A>): Reducer<Map<B, C>, A>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const identity_1 = require("../func/identity");
const push_1 = require("./push");
function groupByMap(key, rfn = push_1.push()) {
function groupByMap(key = identity_1.identity, rfn = push_1.push()) {
return [

@@ -6,0 +7,0 @@ () => new Map(),

@@ -11,3 +11,3 @@ "use strict";

if (reduced_1.isReduced(res)) {
acc.push(reduced_1.unreduced(res));
acc.push(res.deref());
return reduced_1.reduced(acc);

@@ -14,0 +14,0 @@ }

import { Transducer } from "./api";
export declare function step<A, B>(tx: Transducer<A, B>): (x: A) => B;
/**
* Single-step transducer execution wrapper.
* Returns array if transducer produces multiple results
* and undefined if there was no output. Else returns single
* result value.
*
* Likewise, once a transducer has produced a final / reduced
* value, all further invocations of the stepper function will
* return undefined.
*
* ```
* // single result
* step(map(x => x * 10))(1);
* // 10
*
* // multiple results
* step(mapcat(x => [x, x + 1, x + 2]))(1)
* // [ 1, 2, 3 ]
*
* // no result
* f = step(filter(even))
* f(1); // undefined
* f(2); // 2
*
* // reduced value termination
* f = step(take(2));
* f(1); // 1
* f(1); // 1
* f(1); // undefined
* f(1); // undefined
* ```
*
* @param tx
*/
export declare function step<A, B>(tx: Transducer<A, B>): (x: A) => B | B[];
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const last_1 = require("./rfn/last");
const push_1 = require("./rfn/push");
const index_1 = require("./index");
/**
* Single-step transducer execution wrapper.
* Returns array if transducer produces multiple results
* and undefined if there was no output. Else returns single
* result value.
*
* Likewise, once a transducer has produced a final / reduced
* value, all further invocations of the stepper function will
* return undefined.
*
* ```
* // single result
* step(map(x => x * 10))(1);
* // 10
*
* // multiple results
* step(mapcat(x => [x, x + 1, x + 2]))(1)
* // [ 1, 2, 3 ]
*
* // no result
* f = step(filter(even))
* f(1); // undefined
* f(2); // 2
*
* // reduced value termination
* f = step(take(2));
* f(1); // 1
* f(1); // 1
* f(1); // undefined
* f(1); // undefined
* ```
*
* @param tx
*/
function step(tx) {
const rfn = tx(last_1.last())[2];
return (x) => rfn(undefined, x);
const [_, complete, reduce] = tx(push_1.push());
_;
let done = false;
return (x) => {
if (!done) {
let acc = reduce([], x);
done = index_1.isReduced(acc);
if (done) {
acc = complete(acc.deref());
}
return acc.length === 1 ?
acc[0] :
acc.length > 0 ?
acc :
undefined;
}
};
}
exports.step = step;

@@ -1,2 +0,2 @@

const tx = require("../build");
const tx = require("../");

@@ -15,3 +15,3 @@ console.log(

tx.transduce(tx.bits(), tx.push(), [0xaa])
tx.reduce(tx.every(tx.even), tx.range(10))
);
import { Transducer } from "../api";
export declare function cat<T>(): Transducer<T[], T>;
export declare function cat<T>(): Transducer<Iterable<T>, T>;
import { Transducer } from "../api";
/**
* Yields transducer which wraps incoming values in promises, which
* resolve after specified delay time (in ms).
*
* **Only to be used in async contexts and NOT with `transduce` directly.**
*
* @param t
*/
export declare function delayed<T>(t: number): Transducer<T, Promise<T>>;

@@ -5,2 +5,10 @@ "use strict";

const delay_1 = require("../func/delay");
/**
* Yields transducer which wraps incoming values in promises, which
* resolve after specified delay time (in ms).
*
* **Only to be used in async contexts and NOT with `transduce` directly.**
*
* @param t
*/
function delayed(t) {

@@ -7,0 +15,0 @@ return map_1.map((x) => delay_1.delay(x, t));

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const comp_1 = require("../func/comp");
const throttle_1 = require("./throttle");
function dropNth(n) {
n--;
return (rfn) => {
const r = rfn[2];
n = Math.max(0, n - 1);
return throttle_1.throttle(() => {
let skip = n;
return comp_1.compR(rfn, (acc, x) => skip-- > 0 ? r(acc, x) : (skip = n, acc));
};
return () => skip-- > 0 ? true : (skip = n, false);
});
}
exports.dropNth = dropNth;
import { Reducer, Transducer } from "../api";
export declare function scan<A, B>(inner: Reducer<B, A>, acc?: B): Transducer<A, B>;
export declare function scan<A, B>([initi, completei, reducei]: Reducer<B, A>): Transducer<A, B>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const comp_1 = require("../func/comp");
const reduced_1 = require("../reduced");
function scan(inner, acc) {
return (outer) => {
acc = acc || inner[0]();
const ri = inner[2], ro = outer[2];
return comp_1.compR(outer, (_acc, x) => {
acc = ri(acc, x);
if (reduced_1.isReduced(acc)) {
return reduced_1.ensureReduced(ro(_acc, acc.deref()));
function scan([initi, completei, reducei]) {
return ([inito, completeo, reduceo]) => {
let acc = initi();
return [
inito,
(_acc) => {
let a = completei(acc);
if (a !== acc) {
_acc = reduced_1.unreduced(reduceo(_acc, a));
}
acc = a;
return completeo(_acc);
},
(_acc, x) => {
acc = reducei(acc, x);
if (reduced_1.isReduced(acc)) {
return reduced_1.ensureReduced(reduceo(_acc, acc.deref()));
}
return reduceo(_acc, acc);
}
return ro(_acc, acc);
});
];
};
}
exports.scan = scan;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const comp_1 = require("../func/comp");
const throttle_1 = require("./throttle");
function takeNth(n) {
n--;
return (rfn) => {
const r = rfn[2];
n = Math.max(0, n - 1);
return throttle_1.throttle(() => {
let skip = 0;
return comp_1.compR(rfn, (acc, x) => {
if (skip === 0) {
skip = n;
return r(acc, x);
}
skip--;
return acc;
});
};
return () => (skip === 0 ? (skip = n, true) : (skip--, false));
});
}
exports.takeNth = takeNth;

@@ -0,2 +1,18 @@

import { StatefulPredicate } from "@thi.ng/api/api";
import { Transducer } from "../api";
export declare function throttle<T>(delay: number): Transducer<T, T>;
/**
* Similar to `filter`, but works with possibly stateful predicates
* to achieve rate limiting capabilities. Emits only values when
* predicate returns a truthy value.
*
* To support multiple instances of stateful predicates, the predicate
* itself must be wrapped in a no-arg function, which is called when
* the transducer initializes. Any stateful initialization of the
* predicate MUST be done in this function and the function MUST
* return a 1-arg function, the actual predicate applied to each value.
*
* Also see: `throttleTime()`.
*
* @param pred
*/
export declare function throttle<T>(pred: StatefulPredicate<T>): Transducer<T, T>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const comp_1 = require("../func/comp");
function throttle(delay) {
/**
* Similar to `filter`, but works with possibly stateful predicates
* to achieve rate limiting capabilities. Emits only values when
* predicate returns a truthy value.
*
* To support multiple instances of stateful predicates, the predicate
* itself must be wrapped in a no-arg function, which is called when
* the transducer initializes. Any stateful initialization of the
* predicate MUST be done in this function and the function MUST
* return a 1-arg function, the actual predicate applied to each value.
*
* Also see: `throttleTime()`.
*
* @param pred
*/
function throttle(pred) {
return (rfn) => {
const r = rfn[2];
let last = 0;
return comp_1.compR(rfn, (acc, x) => {
const t = Date.now();
if (t - last >= delay) {
last = t;
acc = r(acc, x);
}
return acc;
});
const _pred = pred();
return comp_1.compR(rfn, (acc, x) => _pred(x) ? r(acc, x) : acc);
};
}
exports.throttle = throttle;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc