@rimbu/table
v2.1.5
Published
Immutable spreadsheet-like data structures containing row keys, column keys, and cell values
Maintainers
Readme
@rimbu/table
Immutable, spreadsheet‑like tables for TypeScript & JavaScript.
@rimbu/table provides efficient, type‑safe Table collections: immutable 2‑dimensional maps indexed by row keys and column keys, where each (row, column) pair has at most one value. It also ships concrete variants backed by hashed or sorted maps for both rows and columns.
Use it whenever you need grid‑like data, 2D indexing, or want to avoid juggling nested maps manually.
Table of Contents
- Why
@rimbu/table? - Feature Highlights
- Quick Start
- Core Concepts & Types
- Working with Hash & Sorted Tables
- Performance Notes
- Installation
- FAQ
- Ecosystem & Integration
- Contributing
- License
Why @rimbu/table?
Plain maps give you key → value lookups, but some datasets are naturally 2‑dimensional:
- Spreadsheets and matrices – cells addressed by
(row, column)keys. - Time‑series grids –
userId × day,metric × timeBucket, etc. - Indexing external data – look up a value by two dimensions without nested maps.
@rimbu/table focuses on:
- Row/column semantics – explicit 2D API instead of nested
Map<Map<…>>. - Immutable operations – updates return new instances with structural sharing.
- Configurable backing maps – choose hash or sorted maps for rows and columns.
- Rich traversal utilities – stream by entries, rows, or values.
If you find yourself nesting maps or objects to simulate a grid, a Table is usually a better fit.
Feature Highlights
- 2D lookups – efficient
(row, column) → valueaccess. - Row‑level operations – get, filter, or remove entire rows at once.
- Hash or sorted variants – choose between hashed or ordered semantics for rows and columns.
- Immutable & persistent – structural sharing for fast copies and diffs.
- Configurable contexts – use
Table.createContextor concrete table variants to control underlying map types. - Builder support – mutable builders for efficient bulk construction.
Quick Start
import { HashTableHashColumn } from '@rimbu/table/hash-row';
// Create a hash-based table: hashed rows, hashed columns
const table = HashTableHashColumn.of<[number, string, boolean]>(
[1, 'a', true],
[1, 'b', false],
[2, 'a', false]
);
// Look up a single cell
console.log(table.get(1, 'a')); // true
// Check presence
table.hasRowKey(2); // true
table.hasValueAt(1, 'c'); // false
// Immutable updates
const updated = table.set(2, 'b', true);
console.log(updated.get(2, 'b')); // trueYou can also work with the generic Table interface via a custom context:
import { HashMap } from '@rimbu/hashed';
import { Table } from '@rimbu/table';
// Create a generic Table context using hash maps for rows and columns
const ctx = Table.createContext<number, string>({
rowContext: HashMap.defaultContext<number>(),
columnContext: HashMap.defaultContext<string>(),
});
const t = ctx.of<[number, string, boolean]>([1, 'a', true], [2, 'b', false]);
console.log(t.get(2, 'b')); // false
console.log(t.amountRows); // 2Try Rimbu (including @rimbu/table) live in the browser using the
Rimbu Sandbox on CodeSandbox.
Core Concepts & Types
Exported Types (main package)
From @rimbu/table:
| Name | Description |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Table<R, C, V> | Type‑invariant immutable table of row key type R, column key type C, and value type V. |
| Table.NonEmpty<R, C, V> | Non‑empty refinement of Table<R, C, V> with stronger guarantees. |
| Table.Context<UR, UC> | Factory/context for creating Table instances for upper row type UR and upper column type UC. |
| Table.Builder<R, C, V> | Mutable builder for efficiently constructing or mutating a Table before freezing it into an immutable value. |
| VariantTable<R, C, V> | Type‑variant view over a table; allows safe type‑widening of keys/values without mutation operations. |
| VariantTable.NonEmpty<R, C, V> | Non‑empty refinement of VariantTable<R, C, V>. |
See the full Table docs and API reference for all operations.
Working with Hash & Sorted Tables
The package also exports specialized table types from sub‑packages:
@rimbu/table/hash-rowHashTableHashColumn<R, C, V>– hashed rows, hashed columns.HashTableSortedColumn<R, C, V>– hashed rows, sorted columns.
@rimbu/table/sorted-rowSortedTableHashColumn<R, C, V>– sorted rows, hashed columns.SortedTableSortedColumn<R, C, V>– sorted rows, sorted columns.
Each of these types exports:
*.NonEmpty<R, C, V>– non‑empty refinements.*.Context<UR, UC>– context types.*.Builder<R, C, V>– table builders.
And each has a corresponding creators object:
import {
HashTableHashColumn,
HashTableSortedColumn,
} from '@rimbu/table/hash-row';
import {
SortedTableHashColumn,
SortedTableSortedColumn,
} from '@rimbu/table/sorted-row';
// Hash rows + hash columns
const hh = HashTableHashColumn.empty<number, string, boolean>();
// Hash rows + sorted columns
const hs = HashTableSortedColumn.of<[number, string, number]>(
[1, 'a', 1],
[1, 'b', 2]
);
// Sorted rows + hash columns
const sh = SortedTableHashColumn.from([
[1, 'a', true],
[2, 'b', false],
]);
// Sorted rows + sorted columns
const ss = SortedTableSortedColumn.builder<number, string, number>();Choose the variant based on whether you need ordering for rows and/or columns (use sorted) or just fast hash‑based lookup (use hashed).
Performance Notes
- Tables in Rimbu are built on persistent data structures – updates are typically \(O(\log n)\) and share most of their structure.
- Row and column operations are designed to behave similarly to their underlying map implementations (
HashMap/SortedMap). - Many bulk operations accept generic
StreamSourceinputs, letting you construct and transform tables efficiently from arrays, iterables, or streams.
For detailed performance characteristics and benchmarks, see the main Rimbu documentation at rimbu.org.
Installation
Node / Bun / npm / Yarn
npm install @rimbu/table
# or
yarn add @rimbu/table
# or
bun add @rimbu/table
# or
deno add npm:@rimbu/tableBrowser / ESM
@rimbu/table ships both ESM and CJS builds. Use it with any modern bundler
(Vite, Webpack, esbuild, Bun, etc.) or directly in Node ESM projects.
FAQ
Q: How is a Table different from a nested Map<Map<…>>?
A Table gives you a dedicated 2D API (get, set, getRow, removeRow, etc.), row/column semantics, and consistent immutability guarantees, while still exposing row/column maps when needed.
Q: What happens if I set a value at an existing (row, column)?
The new value replaces the previous one and returns a new table instance; the original is unchanged.
Q: Is the structure mutable?
No. All updates return new table instances; existing ones remain unchanged and can be safely shared across your application.
Q: Can I iterate rows or values separately?
Yes. Use methods like stream, streamRows, streamValues, forEach, or convert to arrays/maps via toArray / rowMap.
Ecosystem & Integration
- Part of the broader Rimbu collection ecosystem – interoperates with
@rimbu/hashed,@rimbu/sorted,@rimbu/collection-types, and@rimbu/stream. - Ideal for modelling grids, cross‑product indices, availability matrices, and more.
- Works seamlessly with other Rimbu collections and utilities for building rich, immutable data models.
Explore more at the Rimbu documentation and the Table API docs.
Contributing
We welcome contributions! See the Contributing guide for details.
Made with contributors-img.
License
MIT © Rimbu contributors. See LICENSE for details.
Attributions
Created and maintained by Arvid Nicolaas. Logo © Rimbu.
