Skip to content

@vizcrush/transform ​

Fast typed-array primitives: radix sort, min-max normalization, range filtering. The boring-but-essential pieces that show up in every data pipeline.

Import ​

typescript
import { sortBy, normalize, filterRange } from "@vizcrush/transform";

sortBy(data, keys?, descending?) ​

Sort a Float64Array in place (or by separate keys) using a radix sort (linear-time on fixed-width floats).

typescript
const data = new Float64Array([3.1, 1.4, 1.5, 9.2, 6.5]);
const sorted = await sortBy(data);
// Float64Array [1.4, 1.5, 3.1, 6.5, 9.2]

Sort one array by another's keys:

typescript
const values = new Float64Array([10, 20, 30, 40]);
const keys = new Float64Array([3, 1, 4, 2]);

const sorted = await sortBy(values, keys);
// values reordered to match keys ascending: [20, 40, 10, 30]

Descending:

typescript
const sorted = await sortBy(data, undefined, /* descending */ true);

Cost: O(n) — radix sort runs in linear time on fixed-width floats. ~3-5× faster than Array.prototype.sort on a million elements.

normalize(data, range?) ​

Min-max normalize to [0, 1] (default) or a custom range:

typescript
const data = new Float64Array([10, 20, 30, 40, 50]);
const normalized = await normalize(data);
// Float64Array [0, 0.25, 0.5, 0.75, 1]

// Custom range:
const scaled = await normalize(data, [-1, 1]);
// Float64Array [-1, -0.5, 0, 0.5, 1]

Useful for:

  • Color mapping in heatmaps and density grids
  • Feeding ML models that expect normalized inputs
  • Coordinate normalization before spatial indexing

filterRange(x, y, xMin, xMax) ​

Extract the subset of (x, y) pairs where x falls within [xMin, xMax]. Returns separate x and y typed arrays.

typescript
const result = await filterRange(x, y, /* xMin */ 1000, /* xMax */ 2000);
// { x: Float64Array, y: Float64Array } for points with 1000 ≤ x ≤ 2000

Use case: viewport zoom. When a user zooms a time-series chart, you don't want to downsample the entire dataset every frame. Filter first, then downsample the filtered slice:

typescript
async function onZoom(visibleMin: number, visibleMax: number) {
  const sliced = await filterRange(x, y, visibleMin, visibleMax);
  const display = await lttb(sliced.x, sliced.y, canvas.width);
  chart.update(display.x, display.y);
}

Performance reference ​

Operation100K500K1M
sortBy5 ms28 ms60 ms
normalize0.3 ms1.5 ms3.0 ms
filterRange (50% viewport)2 ms11 ms19 ms

See also ​

Released under the MIT License.