UNPKG

@rimbu/table

Version:

Immutable spreadsheet-like data structures containing row keys, column keys, and cell values

734 lines 27.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TableContext = exports.TableBuilder = exports.TableNonEmpty = exports.TableEmpty = void 0; var tslib_1 = require("tslib"); var base_1 = require("@rimbu/base"); var map_custom_1 = require("@rimbu/collection-types/map-custom"); var common_1 = require("@rimbu/common"); var stream_1 = require("@rimbu/stream"); var custom_1 = require("@rimbu/stream/custom"); var TableEmpty = /** @class */ (function (_super) { tslib_1.__extends(TableEmpty, _super); function TableEmpty(context) { var _this = _super.call(this) || this; _this.context = context; return _this; } TableEmpty.prototype.set = function (row, column, value) { var columnMap = this.context.columnContext.of([column, value]); var rowMap = this.context.rowContext.of([row, columnMap]); return this.context.createNonEmpty(rowMap, 1); }; Object.defineProperty(TableEmpty.prototype, "rowMap", { get: function () { return this.context.rowContext.empty(); }, enumerable: false, configurable: true }); Object.defineProperty(TableEmpty.prototype, "amountRows", { get: function () { return 0; }, enumerable: false, configurable: true }); TableEmpty.prototype.streamRows = function () { return stream_1.Stream.empty(); }; TableEmpty.prototype.streamValues = function () { return stream_1.Stream.empty(); }; TableEmpty.prototype.addEntry = function (entry) { return this.set(entry[0], entry[1], entry[2]); }; TableEmpty.prototype.addEntries = function (entries) { return this.context.from(entries); }; TableEmpty.prototype.remove = function () { return this; }; TableEmpty.prototype.removeRow = function () { return this; }; TableEmpty.prototype.removeRows = function () { return this; }; TableEmpty.prototype.removeAndGet = function () { return undefined; }; TableEmpty.prototype.removeRowAndGet = function () { return undefined; }; TableEmpty.prototype.removeEntries = function () { return this; }; TableEmpty.prototype.hasRowKey = function () { return false; }; TableEmpty.prototype.hasValueAt = function () { return false; }; TableEmpty.prototype.get = function (row, column, otherwise) { return (0, common_1.OptLazy)(otherwise); }; TableEmpty.prototype.getRow = function () { return this.context.columnContext.empty(); }; TableEmpty.prototype.modifyAt = function (row, column, options) { if (undefined !== options.ifNew) { var value = (0, common_1.OptLazyOr)(options.ifNew, base_1.Token); if (base_1.Token === value) return this; return this.set(row, column, value); } return this; }; TableEmpty.prototype.updateAt = function () { return this; }; TableEmpty.prototype.filterRows = function () { return this; }; TableEmpty.prototype.mapValues = function () { return this; }; TableEmpty.prototype.toBuilder = function () { return this.context.builder(); }; TableEmpty.prototype.toString = function () { return "".concat(this.context.typeTag, "()"); }; TableEmpty.prototype.toJSON = function () { return { dataType: this.context.typeTag, value: [], }; }; return TableEmpty; }(map_custom_1.EmptyBase)); exports.TableEmpty = TableEmpty; var TableNonEmpty = /** @class */ (function (_super) { tslib_1.__extends(TableNonEmpty, _super); function TableNonEmpty(context, rowMap, size) { var _this = _super.call(this) || this; _this.context = context; _this.rowMap = rowMap; _this.size = size; return _this; } TableNonEmpty.prototype.assumeNonEmpty = function () { return this; }; TableNonEmpty.prototype.asNormal = function () { return this; }; TableNonEmpty.prototype.copy = function (rowMap, size) { if (rowMap === this.rowMap) return this; return this.context.createNonEmpty(rowMap, size); }; TableNonEmpty.prototype.copyE = function (rowMap, size) { if (rowMap.nonEmpty()) { return this.copy(rowMap.assumeNonEmpty(), size); } return this.context.empty(); }; TableNonEmpty.prototype.stream = function () { return this.rowMap .stream() .flatMap(function (_a) { var _b = tslib_1.__read(_a, 2), row = _b[0], columns = _b[1]; return columns .stream() .map(function (_a) { var _b = tslib_1.__read(_a, 2), column = _b[0], value = _b[1]; return [row, column, value]; }); }); }; TableNonEmpty.prototype.streamRows = function () { return this.rowMap.streamKeys(); }; TableNonEmpty.prototype.streamValues = function () { return this.rowMap .streamValues() .flatMap(function (columns) { return columns.streamValues(); }); }; Object.defineProperty(TableNonEmpty.prototype, "amountRows", { get: function () { return this.rowMap.size; }, enumerable: false, configurable: true }); TableNonEmpty.prototype.hasRowKey = function (row) { return this.rowMap.hasKey(row); }; TableNonEmpty.prototype.hasValueAt = function (row, column) { var token = Symbol(); return token !== this.get(row, column, token); }; TableNonEmpty.prototype.get = function (row, column, otherwise) { var token = Symbol(); var result = this.rowMap.get(row, token); if (token === result) return (0, common_1.OptLazy)(otherwise); return result.get(column, otherwise); }; TableNonEmpty.prototype.getRow = function (row) { return this.rowMap.get(row, this.context.columnContext.empty()); }; TableNonEmpty.prototype.set = function (row, column, value) { return this.modifyAt(row, column, { ifNew: value, ifExists: function () { return value; }, }).assumeNonEmpty(); }; TableNonEmpty.prototype.addEntry = function (entry) { return this.set(entry[0], entry[1], entry[2]); }; TableNonEmpty.prototype.addEntries = function (entries) { if ((0, custom_1.isEmptyStreamSourceInstance)(entries)) return this; var builder = this.toBuilder(); builder.addEntries(entries); return builder.build().assumeNonEmpty(); }; TableNonEmpty.prototype.modifyAt = function (row, column, options) { var _this = this; var newSize = this.size; var newRowMap = this.rowMap.modifyAt(row, { ifNew: function (none) { var ifNew = options.ifNew; if (undefined === ifNew) { return none; } var value = (0, common_1.OptLazyOr)(ifNew, none); if (none === value) { return none; } newSize++; return _this.context.columnContext.of([column, value]); }, ifExists: function (row, remove) { var newRow = row.modifyAt(column, options); if (newRow === row) { return row; } if (!newRow.nonEmpty()) { return remove; } newSize += newRow.size - row.size; return newRow; }, }); return this.copyE(newRowMap, newSize); }; TableNonEmpty.prototype.updateAt = function (row, column, update) { if (!this.context.rowContext.isValidKey(row)) return this; if (!this.context.columnContext.isValidKey(column)) return this; return this.modifyAt(row, column, { ifExists: function (value) { return (0, common_1.Update)(value, update); }, }).assumeNonEmpty(); }; TableNonEmpty.prototype.remove = function (row, column) { var _a; var resultOpt = this.removeAndGet(row, column); return (_a = resultOpt === null || resultOpt === void 0 ? void 0 : resultOpt[0]) !== null && _a !== void 0 ? _a : this; }; TableNonEmpty.prototype.removeRow = function (row) { var _a; var resultOpt = this.removeRowAndGet(row); return (_a = resultOpt === null || resultOpt === void 0 ? void 0 : resultOpt[0]) !== null && _a !== void 0 ? _a : this; }; TableNonEmpty.prototype.removeRows = function (rows) { if ((0, custom_1.isEmptyStreamSourceInstance)(rows)) return this; var builder = this.toBuilder(); builder.removeRows(rows); return builder.build(); }; TableNonEmpty.prototype.removeAndGet = function (row, column) { if (!this.context.rowContext.isValidKey(row)) return undefined; if (!this.context.columnContext.isValidKey(column)) return undefined; var newSize = this.size; var token = Symbol(); var removedValue = token; var newRows = this.rowMap.modifyAt(row, { ifExists: function (columns, remove) { var newColumns = columns.modifyAt(column, { ifExists: function (currentValue, remove) { removedValue = currentValue; newSize--; return remove; }, }); if (newColumns.nonEmpty()) return newColumns; return remove; }, }); if (token === removedValue) return undefined; var newSelf = this.copyE(newRows, newSize); return [newSelf, removedValue]; }; TableNonEmpty.prototype.removeRowAndGet = function (row) { if (!this.context.rowContext.isValidKey(row)) return undefined; var newSize = this.size; var removedRow; var newRows = this.rowMap.modifyAt(row, { ifExists: function (columns, remove) { removedRow = columns; newSize -= columns.size; return remove; }, }); if (undefined === removedRow) return undefined; var newSelf = this.copyE(newRows, newSize); return [newSelf, removedRow]; }; TableNonEmpty.prototype.removeEntries = function (entries) { if ((0, custom_1.isEmptyStreamSourceInstance)(entries)) return this; var builder = this.toBuilder(); builder.removeEntries(entries); return builder.build(); }; TableNonEmpty.prototype.forEach = function (f, options) { if (options === void 0) { options = {}; } var _a = options.state, state = _a === void 0 ? (0, common_1.TraverseState)() : _a; if (state.halted) return; var rowIt = this.rowMap[Symbol.iterator](); var rowEntry; var halt = state.halt; while (!state.halted && undefined !== (rowEntry = rowIt.fastNext())) { var columnIt = rowEntry[1][Symbol.iterator](); var columnEntry = void 0; while (!state.halted && undefined !== (columnEntry = columnIt.fastNext())) { f([rowEntry[0], columnEntry[0], columnEntry[1]], state.nextIndex(), halt); } } }; TableNonEmpty.prototype.filter = function (pred, options) { if (options === void 0) { options = {}; } var builder = this.context.builder(); builder.addEntries(this.stream().filter(pred, options)); if (builder.size === this.size) return this; return builder.build(); }; TableNonEmpty.prototype.filterRows = function (pred, options) { if (options === void 0) { options = {}; } var _a = options.negate, negate = _a === void 0 ? false : _a; var newSize = 0; var newRowMap = this.rowMap.filter(function (e, i, halt) { var result = pred(e, i, halt); if (result !== negate) newSize += e[1].size; return result; }); return this.copyE(newRowMap, newSize); }; TableNonEmpty.prototype.mapValues = function (mapFun) { return this.copy(this.rowMap.mapValues(function (row, r) { return row.mapValues(function (v, c) { return mapFun(v, r, c); }); }), this.size); }; TableNonEmpty.prototype.toArray = function () { var result = []; var rowIt = this.rowMap.stream()[Symbol.iterator](); var rowEntry; while (undefined !== (rowEntry = rowIt.fastNext())) { var columnIt = rowEntry[1].stream()[Symbol.iterator](); var columnEntry = void 0; while (undefined !== (columnEntry = columnIt.fastNext())) { result.push([rowEntry[0], columnEntry[0], columnEntry[1]]); } } return result; }; TableNonEmpty.prototype.toString = function () { return this.stream().join({ start: "".concat(this.context.typeTag, "("), sep: ", ", end: ")", valueToString: function (entry) { return "[".concat(entry[0], ", ").concat(entry[1], "] -> ").concat(entry[2]); }, }); }; TableNonEmpty.prototype.toJSON = function () { return { dataType: this.context.typeTag, value: this.rowMap .stream() .map(function (entry) { return [entry[0], entry[1].toJSON().value]; }) .toArray(), }; }; TableNonEmpty.prototype.toBuilder = function () { return this.context.createBuilder(this); }; return TableNonEmpty; }(map_custom_1.NonEmptyBase)); exports.TableNonEmpty = TableNonEmpty; var TableBuilder = /** @class */ (function () { function TableBuilder(context, source) { var _this = this; this.context = context; this.source = source; //implements TableBase.Builder<R, C, V> this._lock = 0; this._size = 0; this.get = function (row, column, otherwise) { if (undefined !== _this.source) { return _this.source.get(row, column, otherwise); } var token = Symbol(); var result = _this.rowMap.get(row, token); if (token === result) return (0, common_1.OptLazy)(otherwise); return result.get(column, otherwise); }; // prettier-ignore this.getRow = function (row) { if (undefined !== _this.source) return _this.source.getRow(row); var token = Symbol(); var result = _this.rowMap.get(row, token); if (token === result) return _this.context.columnContext.empty(); return result.build(); }; this.hasValueAt = function (row, column) { if (undefined !== _this.source) return _this.source.hasValueAt(row, column); var token = Symbol(); return token !== _this.get(row, column, token); }; // prettier-ignore this.hasRowKey = function (row) { var _a, _b; return (_b = (_a = _this.source) === null || _a === void 0 ? void 0 : _a.hasRowKey(row)) !== null && _b !== void 0 ? _b : _this.rowMap.hasKey(row); }; this.set = function (row, column, value) { _this.checkLock(); var columnBuilder = undefined; _this.rowMap.modifyAt(row, { ifNew: function () { columnBuilder = _this.context.columnContext.builder(); return columnBuilder; }, ifExists: function (b) { columnBuilder = b; return b; }, }); var changed = true; columnBuilder.modifyAt(column, { ifNew: function () { _this._size++; return value; }, ifExists: function (currentValue) { if (Object.is(currentValue, value)) changed = false; return value; }, }); if (changed) _this.source = undefined; return changed; }; this.addEntry = function (entry) { return _this.set(entry[0], entry[1], entry[2]); }; this.addEntries = function (source) { _this.checkLock(); return stream_1.Stream.applyFilter(source, { pred: _this.set }).count() > 0; }; this.remove = function (row, column, otherwise) { _this.checkLock(); var columnMap = _this.rowMap.get(row); if (undefined === columnMap) return (0, common_1.OptLazy)(otherwise); if (!_this.context.columnContext.isValidKey(column)) { return (0, common_1.OptLazy)(otherwise); } var removedValue = base_1.Token; columnMap.modifyAt(column, { ifExists: function (currentValue, remove) { removedValue = currentValue; _this._size--; return remove; }, }); if (columnMap.isEmpty) _this.rowMap.removeKey(row); if (base_1.Token === removedValue) return (0, common_1.OptLazy)(otherwise); _this.source = undefined; return removedValue; }; // prettier-ignore this.removeRow = function (row) { _this.checkLock(); if (!_this.context.rowContext.isValidKey(row)) return false; return _this.rowMap.modifyAt(row, { ifExists: function (row, remove) { _this.source = undefined; _this._size -= row.size; return remove; }, }); }; // prettier-ignore this.removeRows = function (rows) { _this.checkLock(); return stream_1.Stream.from(rows).filterPure({ pred: _this.removeRow }).count() > 0; }; this.removeEntries = function (entries) { _this.checkLock(); var notFound = Symbol(); return (stream_1.Stream.applyMap(entries, _this.remove, notFound).countElement(notFound, { negate: true, }) > 0); }; this.modifyAt = function (row, column, options) { _this.checkLock(); var changed = false; _this.rowMap.modifyAt(row, { ifNew: function (none) { var ifNew = options.ifNew; if (undefined === ifNew) { return none; } var newValue = (0, common_1.OptLazyOr)(ifNew, none); if (newValue === none) { return none; } var rowMap = _this.context.columnContext.builder(); rowMap.set(column, newValue); changed = true; _this._size++; return rowMap; }, ifExists: function (curMap, remove) { var preSize = curMap.size; changed = curMap.modifyAt(column, options); if (changed) { var postSize = curMap.size; _this._size += postSize - preSize; if (postSize <= 0) { return remove; } } return curMap; }, }); if (changed) { _this.source = undefined; } return changed; }; // prettier-ignore this.updateAt = function (row, column, update, otherwise) { _this.checkLock(); var oldValue; var found = false; _this.modifyAt(row, column, { ifExists: function (value) { oldValue = value; found = true; return (0, common_1.Update)(value, update); }, }); if (!found) return (0, common_1.OptLazy)(otherwise); _this.source = undefined; return oldValue; }; this.forEach = function (f, options) { if (options === void 0) { options = {}; } var _a = options.state, state = _a === void 0 ? (0, common_1.TraverseState)() : _a; if (state.halted) return; _this._lock++; if (undefined !== _this.source) { _this.source.forEach(f, { state: state }); } else { var halt_1 = state.halt; _this.rowMap.forEach(function (_a, _, rowHalt) { var _b = tslib_1.__read(_a, 2), rowKey = _b[0], column = _b[1]; column.forEach(function (_a, _, columnHalt) { var _b = tslib_1.__read(_a, 2), columnKey = _b[0], value = _b[1]; f([rowKey, columnKey, value], state.nextIndex(), halt_1); if (state.halted) { rowHalt(); columnHalt(); } }); }); } _this._lock--; }; this.build = function () { if (undefined !== _this.source) return _this.source; if (_this.isEmpty) return _this.context.empty(); return _this.context.createNonEmpty(_this.rowMap .buildMapValues(function (row) { return row.build().assumeNonEmpty(); }) .assumeNonEmpty(), _this.size); }; // prettier-ignore this.buildMapValues = function (mapFun) { if (undefined !== _this.source) return _this.source.mapValues(mapFun); if (_this.isEmpty) return _this.context.empty(); var newRowMap = _this.rowMap .buildMapValues(function (row, rowKey) { return row .buildMapValues(function (value, columnKey) { return mapFun(value, rowKey, columnKey); }) .assumeNonEmpty(); }) .assumeNonEmpty(); return _this.context.createNonEmpty(newRowMap, _this.size); }; if (undefined !== source) this._size = source.size; } Object.defineProperty(TableBuilder.prototype, "rowMap", { get: function () { if (undefined === this._rowMap) { if (undefined === this.source) { this._rowMap = this.context.rowContext.builder(); } else { this._rowMap = this.source.rowMap .mapValues(function (v) { return v.toBuilder(); }) .toBuilder(); } } return this._rowMap; }, enumerable: false, configurable: true }); TableBuilder.prototype.checkLock = function () { if (this._lock) base_1.RimbuError.throwModifiedBuilderWhileLoopingOverItError(); }; Object.defineProperty(TableBuilder.prototype, "size", { get: function () { return this._size; }, enumerable: false, configurable: true }); Object.defineProperty(TableBuilder.prototype, "isEmpty", { get: function () { return this.size === 0; }, enumerable: false, configurable: true }); Object.defineProperty(TableBuilder.prototype, "amountRows", { get: function () { var _a, _b; return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.amountRows) !== null && _b !== void 0 ? _b : this.rowMap.size; }, enumerable: false, configurable: true }); return TableBuilder; }()); exports.TableBuilder = TableBuilder; var TableContext = /** @class */ (function () { function TableContext(typeTag, rowContext, columnContext) { var _this = this; this.typeTag = typeTag; this.rowContext = rowContext; this.columnContext = columnContext; this._empty = Object.freeze(new TableEmpty(this)); this.empty = function () { return _this._empty; }; this.from = function () { var sources = []; for (var _i = 0; _i < arguments.length; _i++) { sources[_i] = arguments[_i]; } var builder = _this.builder(); var i = -1; var length = sources.length; while (++i < length) { var source = sources[i]; if ((0, custom_1.isEmptyStreamSourceInstance)(source)) continue; if (builder.isEmpty && _this.isNonEmptyInstance(source) && source.context === _this) { if (i === length - 1) return source; builder = source.toBuilder(); continue; } builder.addEntries(source); } return builder.build(); }; this.of = function () { var entries = []; for (var _i = 0; _i < arguments.length; _i++) { entries[_i] = arguments[_i]; } return _this.from(entries); }; this.builder = function () { return new TableBuilder(_this); }; this.reducer = function (source) { return stream_1.Reducer.create(function () { return undefined === source ? _this.builder() : _this.from(source).toBuilder(); }, function (builder, entry) { builder.addEntry(entry); return builder; }, function (builder) { return builder.build(); }); }; } Object.defineProperty(TableContext.prototype, "_types", { get: function () { return undefined; }, enumerable: false, configurable: true }); TableContext.prototype.isNonEmptyInstance = function (source) { return source instanceof TableNonEmpty; }; TableContext.prototype.createNonEmpty = function (rowMap, size) { return new TableNonEmpty(this, rowMap, size); }; TableContext.prototype.createBuilder = function (source) { return new TableBuilder(this, source); }; return TableContext; }()); exports.TableContext = TableContext; //# sourceMappingURL=base.cjs.map