UNPKG

@rimbu/multiset

Version:

An immutable Set where each element can occur multiple times

580 lines 21.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultiSetContext = exports.MultiSetBuilder = exports.MultiSetNonEmpty = exports.MultiSetEmpty = void 0; var tslib_1 = require("tslib"); var base_1 = require("@rimbu/base"); var map_custom_1 = require("@rimbu/collection-types/map-custom"); var stream_1 = require("@rimbu/stream"); var custom_1 = require("@rimbu/stream/custom"); var common_1 = require("@rimbu/common"); var MultiSetEmpty = /** @class */ (function (_super) { tslib_1.__extends(MultiSetEmpty, _super); function MultiSetEmpty(context) { var _this = _super.call(this) || this; _this.context = context; return _this; } MultiSetEmpty.prototype.add = function (elem, amount) { if (undefined !== amount && amount <= 0) return this; var addAmount = amount !== null && amount !== void 0 ? amount : 1; var countMap = this.context.countMapContext.of([ elem, addAmount, ]); return this.context.createNonEmpty(countMap, addAmount); }; Object.defineProperty(MultiSetEmpty.prototype, "countMap", { get: function () { return this.context.countMapContext.empty(); }, enumerable: false, configurable: true }); Object.defineProperty(MultiSetEmpty.prototype, "sizeDistinct", { get: function () { return 0; }, enumerable: false, configurable: true }); MultiSetEmpty.prototype.streamDistinct = function () { return stream_1.Stream.empty(); }; MultiSetEmpty.prototype.addAll = function (values) { return this.context.from(values); }; MultiSetEmpty.prototype.addEntries = function (entries) { if ((0, custom_1.isEmptyStreamSourceInstance)(entries)) return this; var builder = this.toBuilder(); builder.addEntries(entries); return builder.build(); }; MultiSetEmpty.prototype.remove = function () { return this; }; MultiSetEmpty.prototype.removeAllSingle = function () { return this; }; MultiSetEmpty.prototype.removeAllEvery = function () { return this; }; MultiSetEmpty.prototype.setCount = function (elem, amount) { return this.add(elem, amount); }; MultiSetEmpty.prototype.modifyCount = function (value, update) { return this.add(value, update(0)); }; MultiSetEmpty.prototype.has = function () { return false; }; MultiSetEmpty.prototype.count = function () { return 0; }; MultiSetEmpty.prototype.forEach = function () { // }; MultiSetEmpty.prototype.filterEntries = function () { return this; }; MultiSetEmpty.prototype.toBuilder = function () { return this.context.builder(); }; MultiSetEmpty.prototype.toArray = function () { return []; }; MultiSetEmpty.prototype.toString = function () { return "".concat(this.context.typeTag, "()"); }; MultiSetEmpty.prototype.toJSON = function () { return { dataType: this.context.typeTag, value: [], }; }; return MultiSetEmpty; }(map_custom_1.EmptyBase)); exports.MultiSetEmpty = MultiSetEmpty; var MultiSetNonEmpty = /** @class */ (function (_super) { tslib_1.__extends(MultiSetNonEmpty, _super); function MultiSetNonEmpty(context, countMap, size) { var _this = _super.call(this) || this; _this.context = context; _this.countMap = countMap; _this.size = size; return _this; } MultiSetNonEmpty.prototype.assumeNonEmpty = function () { return this; }; MultiSetNonEmpty.prototype.copy = function (countMap, size) { if (countMap === this.countMap) return this; return this.context.createNonEmpty(countMap, size); }; MultiSetNonEmpty.prototype.copyE = function (countMap, size) { if (countMap.nonEmpty()) return this.copy(countMap, size); return this.context.empty(); }; Object.defineProperty(MultiSetNonEmpty.prototype, "sizeDistinct", { get: function () { return this.countMap.size; }, enumerable: false, configurable: true }); MultiSetNonEmpty.prototype.stream = function () { return this.countMap .stream() .flatMap(function (_a) { var _b = tslib_1.__read(_a, 2), value = _b[0], count = _b[1]; return stream_1.Stream.of(value).repeat(count); }); }; MultiSetNonEmpty.prototype.streamDistinct = function () { return this.countMap.streamKeys(); }; MultiSetNonEmpty.prototype.has = function (elem) { return this.countMap.hasKey(elem); }; MultiSetNonEmpty.prototype.count = function (elem) { return this.countMap.get(elem, 0); }; MultiSetNonEmpty.prototype.add = function (elem, amount) { if (amount === void 0) { amount = 1; } if (amount <= 0) return this; return this.copy(this.countMap .modifyAt(elem, { ifNew: amount, ifExists: function (count) { return count + amount; }, }) .assumeNonEmpty(), this.size + amount); }; MultiSetNonEmpty.prototype.addAll = function (values) { if ((0, custom_1.isEmptyStreamSourceInstance)(values)) return this; var builder = this.toBuilder(); builder.addAll(values); return builder.build().assumeNonEmpty(); }; MultiSetNonEmpty.prototype.addEntries = function (entries) { if ((0, custom_1.isEmptyStreamSourceInstance)(entries)) return this; var builder = this.toBuilder(); builder.addEntries(entries); return builder.build().assumeNonEmpty(); }; MultiSetNonEmpty.prototype.setCount = function (elem, amount) { if (amount <= 0) return this.remove(elem); var sizeDelta = amount; var newCountMap = this.countMap .modifyAt(elem, { ifNew: amount, ifExists: function (count) { sizeDelta -= count; return amount; }, }) .assumeNonEmpty(); return this.copyE(newCountMap, this.size + sizeDelta); }; MultiSetNonEmpty.prototype.modifyCount = function (value, update) { var sizeDelta = 0; var newCountMap = this.countMap .modifyAt(value, { ifNew: function (none) { var newAmount = update(0); if (newAmount <= 0) return none; sizeDelta += newAmount; return newAmount; }, ifExists: function (amount, remove) { sizeDelta -= amount; var newAmount = update(amount); if (newAmount <= 0) return remove; sizeDelta += newAmount; return newAmount; }, }) .assumeNonEmpty(); return this.copyE(newCountMap, this.size + sizeDelta); }; MultiSetNonEmpty.prototype.remove = function (elem, options) { if (options === void 0) { options = {}; } var _a = options.amount, amount = _a === void 0 ? 1 : _a; if (!this.context.isValidElem(elem)) return this; var newSize = this.size; var newCountMap = this.countMap.modifyAt(elem, { ifExists: function (count, remove) { if (amount === 'ALL') { newSize -= count; return remove; } var result = count - amount; if (result <= 0) { newSize -= count; return remove; } newSize -= amount; return result; }, }); return this.copyE(newCountMap, newSize); }; MultiSetNonEmpty.prototype.removeAllSingle = function (elems) { if ((0, custom_1.isEmptyStreamSourceInstance)(elems)) return this; var builder = this.toBuilder(); builder.removeAllSingle(elems); return builder.build(); }; MultiSetNonEmpty.prototype.removeAllEvery = function (elems) { if ((0, custom_1.isEmptyStreamSourceInstance)(elems)) return this; var builder = this.toBuilder(); builder.removeAllEvery(elems); return builder.build(); }; MultiSetNonEmpty.prototype.forEach = function (f, options) { if (options === void 0) { options = {}; } var _a = options.reversed, reversed = _a === void 0 ? false : _a, _b = options.state, state = _b === void 0 ? (0, common_1.TraverseState)() : _b; if (state.halted) return; var it = this.countMap.stream({ reversed: reversed })[Symbol.iterator](); var entry; var halt = state.halt; while (!state.halted && undefined !== (entry = it.fastNext())) { var value = entry[0]; var amount = entry[1]; while (!state.halted && --amount >= 0) { f(value, state.nextIndex(), halt); } } }; MultiSetNonEmpty.prototype.filterEntries = function (pred, options) { if (options === void 0) { options = {}; } var builder = this.context.builder(); stream_1.Stream.applyForEach(this.countMap.stream().filter(pred, options), builder.setCount); if (builder.size === this.size) return this; return builder.build(); }; MultiSetNonEmpty.prototype.toArray = function () { var result = []; var it = this.countMap[Symbol.iterator](); var entry; while (undefined !== (entry = it.fastNext())) { var amount = entry[1]; if (amount === 1) result.push(entry[0]); else { var newArray = new Array(amount); newArray.fill(entry[0]); result = base_1.Arr.concat(result, newArray); } } return result; }; MultiSetNonEmpty.prototype.toString = function () { return this.stream().join({ start: "".concat(this.context.typeTag, "("), sep: ", ", end: ")", }); }; MultiSetNonEmpty.prototype.toJSON = function () { return { dataType: this.context.typeTag, value: this.countMap.toArray(), }; }; MultiSetNonEmpty.prototype.toBuilder = function () { return new MultiSetBuilder(this.context, this); }; return MultiSetNonEmpty; }(map_custom_1.NonEmptyBase)); exports.MultiSetNonEmpty = MultiSetNonEmpty; var MultiSetBuilder = /** @class */ (function () { function MultiSetBuilder(context, source) { var _this = this; this.context = context; this.source = source; this._lock = 0; this._size = 0; // prettier-ignore this.has = function (value) { var _a, _b; return (_b = (_a = _this.source) === null || _a === void 0 ? void 0 : _a.has(value)) !== null && _b !== void 0 ? _b : _this.countMap.hasKey(value); }; this.add = function (value, amount) { if (amount === void 0) { amount = 1; } _this.checkLock(); if (amount <= 0) return false; _this._size += amount; _this.countMap.modifyAt(value, { ifNew: amount, ifExists: function (count) { return count + amount; }, }); _this.source = undefined; return true; }; this.addAll = function (source) { _this.checkLock(); return stream_1.Stream.from(source).filterPure({ pred: _this.add }, 1).count() > 0; }; this.addEntries = function (entries) { _this.checkLock(); return stream_1.Stream.applyFilter(entries, { pred: _this.add }).count() > 0; }; // prettier-ignore this.remove = function (value, amount) { if (amount === void 0) { amount = 1; } _this.checkLock(); if (typeof amount === 'number' && amount <= 0) return 0; if (!_this.context.isValidElem(value)) return 0; var removed = 0; _this.countMap.modifyAt(value, { ifExists: function (count, remove) { if (amount === 'ALL') { removed = count; return remove; } var result = count - amount; if (result <= 0) { removed = count; return remove; } removed = amount; return result; }, }); _this._size -= removed; if (removed > 0) _this.source = undefined; return removed; }; this.setCount = function (value, amount) { _this.checkLock(); if (amount <= 0) { return _this.remove(value, 'ALL') > 0; } _this._size += amount; var changed = _this.countMap.modifyAt(value, { ifNew: amount, ifExists: function (count) { _this._size -= count; return amount; }, }); if (changed) _this.source = undefined; return changed; }; this.modifyCount = function (value, update) { _this.checkLock(); var changed = _this.countMap.modifyAt(value, { ifNew: function (none) { var newAmount = update(0); if (newAmount <= 0) return none; _this._size += newAmount; return newAmount; }, ifExists: function (currentCount, remove) { _this._size -= currentCount; var newCount = update(currentCount); if (newCount <= 0) return remove; _this._size += newCount; return newCount; }, }); if (changed) _this.source = undefined; return changed; }; // prettier-ignore this.count = function (value) { var _a, _b; return (_b = (_a = _this.source) === null || _a === void 0 ? void 0 : _a.count(value)) !== null && _b !== void 0 ? _b : _this.countMap.get(value, 0); }; // prettier-ignore this.removeAll = function (values, mode) { _this.checkLock(); if ((0, custom_1.isEmptyStreamSourceInstance)(values)) return false; return (stream_1.Stream.from(values) .mapPure(_this.remove, mode === 'SINGLE' ? 1 : 'ALL') .countElement(0, { negate: true }) > 0); }; // prettier-ignore this.removeAllSingle = function (values) { return _this.removeAll(values, 'SINGLE'); }; // prettier-ignore this.removeAllEvery = function (values) { return _this.removeAll(values, 'ALL'); }; 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++; var halt = state.halt; _this.countMap.forEach(function (_a, _, builderHalt) { var _b = tslib_1.__read(_a, 2), value = _b[0], amount = _b[1]; var time = 0; while (!state.halted && time++ < amount) { f(value, state.nextIndex(), halt); } if (state.halted) builderHalt(); }); _this._lock--; }; this.build = function () { if (undefined !== _this.source) return _this.source; if (_this.isEmpty) return _this.context.empty(); var newCountMap = _this.countMap .build() .assumeNonEmpty(); return new MultiSetNonEmpty(_this.context, newCountMap, _this.size); }; if (undefined !== source) this._size = source.size; } Object.defineProperty(MultiSetBuilder.prototype, "countMap", { get: function () { if (undefined === this._countMap) { if (undefined === this.source) { this._countMap = this.context.countMapContext.builder(); } else { this._countMap = this.source.countMap.toBuilder(); } } return this._countMap; }, enumerable: false, configurable: true }); MultiSetBuilder.prototype.checkLock = function () { if (this._lock) base_1.RimbuError.throwModifiedBuilderWhileLoopingOverItError(); }; Object.defineProperty(MultiSetBuilder.prototype, "size", { get: function () { return this._size; }, enumerable: false, configurable: true }); Object.defineProperty(MultiSetBuilder.prototype, "sizeDistinct", { get: function () { var _a, _b; return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.sizeDistinct) !== null && _b !== void 0 ? _b : this.countMap.size; }, enumerable: false, configurable: true }); Object.defineProperty(MultiSetBuilder.prototype, "isEmpty", { get: function () { return 0 === this.size; }, enumerable: false, configurable: true }); return MultiSetBuilder; }()); exports.MultiSetBuilder = MultiSetBuilder; var MultiSetContext = /** @class */ (function () { function MultiSetContext(typeTag, countMapContext) { var _this = this; this.typeTag = typeTag; this.countMapContext = countMapContext; this._empty = Object.freeze(new MultiSetEmpty(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.addAll(source); } return builder.build(); }; // prettier-ignore this.of = function () { var values = []; for (var _i = 0; _i < arguments.length; _i++) { values[_i] = arguments[_i]; } return _this.from(values); }; this.builder = function () { return new MultiSetBuilder(_this); }; this.reducer = function (source) { return stream_1.Reducer.create(function () { return undefined === source ? _this.builder() : _this.from(source).toBuilder(); }, function (builder, value) { builder.add(value); return builder; }, function (builder) { return builder.build(); }); }; } Object.defineProperty(MultiSetContext.prototype, "_types", { get: function () { return undefined; }, enumerable: false, configurable: true }); MultiSetContext.prototype.isValidElem = function (elem) { return this.countMapContext.isValidKey(elem); }; MultiSetContext.prototype.isNonEmptyInstance = function (source) { return source instanceof MultiSetNonEmpty; }; MultiSetContext.prototype.createNonEmpty = function (countMap, size) { return new MultiSetNonEmpty(this, countMap, size); }; MultiSetContext.prototype.createBuilder = function (source) { return new MultiSetBuilder(this, source); }; return MultiSetContext; }()); exports.MultiSetContext = MultiSetContext; //# sourceMappingURL=base.cjs.map