UNPKG

linqcontainers

Version:

Linq-Collections (ES5): [IEnumerable, IQueryable, ...] + [List, Dictionary, Stack, ... + readonly]

755 lines 28.4 kB
"use strict"; // - // Created by Ivan Sanz (@isc30) // Copyright © 2017 Ivan Sanz Carasa. All rights reserved. // - var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var Collections_1 = require("./Collections"); var Iterators_1 = require("./Iterators"); var Comparers_1 = require("./Comparers"); var Utils_1 = require("./Utils"); // endregion // region EnumerableBase var EnumerableBase = /** @class */ (function () { function EnumerableBase(source) { this.source = source; } EnumerableBase.prototype.reset = function () { this.source.reset(); }; EnumerableBase.prototype.next = function () { return this.source.next(); }; EnumerableBase.prototype.asEnumerable = function () { return this; }; EnumerableBase.prototype.toArray = function () { var result = []; this.reset(); while (this.next()) { result.push(this.value()); } return result; }; EnumerableBase.prototype.toList = function () { return new Collections_1.List(this.toArray()); }; EnumerableBase.prototype.toDictionary = function (keySelector, valueSelector) { return Collections_1.Dictionary.fromArray(this.toArray(), keySelector, valueSelector); }; EnumerableBase.prototype.count = function (predicate) { if (predicate !== undefined) { // Don't copy iterators return new ConditionalEnumerable(this, predicate).count(); } var result = 0; this.reset(); while (this.next()) { ++result; } // tslint:disable-next-line:no-bitwise return result >>> 0; }; EnumerableBase.prototype.any = function (predicate) { if (predicate !== undefined) { // Don't copy iterators return new ConditionalEnumerable(this, predicate).any(); } this.reset(); return this.next(); }; EnumerableBase.prototype.all = function (predicate) { this.reset(); while (this.next()) { if (!predicate(this.value())) { return false; } } return true; }; EnumerableBase.prototype.reverse = function () { return new ReverseEnumerable(this.copy()); }; EnumerableBase.prototype.contains = function (element) { return this.any(function (e) { return e === element; }); }; EnumerableBase.prototype.where = function (predicate) { return new ConditionalEnumerable(this.copy(), predicate); }; EnumerableBase.prototype.select = function (selector) { return new TransformEnumerable(this.copy(), selector); }; EnumerableBase.prototype.selectMany = function (selector) { var selectToEnumerable = function (e) { var ie = selector(e); return Array.isArray(ie) ? new ArrayEnumerable(ie) : ie.asEnumerable(); }; return this .select(selectToEnumerable).toArray() .reduce(function (p, c) { return new ConcatEnumerable(p, c); }, Enumerable.empty()); }; EnumerableBase.prototype.concat = function (other) { var others = []; for (var _i = 1; _i < arguments.length; _i++) { others[_i - 1] = arguments[_i]; } var asEnumerable = function (e) { return Array.isArray(e) ? new ArrayEnumerable(e) : e.asEnumerable(); }; var result = new ConcatEnumerable(this.copy(), asEnumerable(other).copy()); for (var i = 0, end = others.length; i < end; ++i) { result = new ConcatEnumerable(result, asEnumerable(others[i]).copy()); } return result; }; EnumerableBase.prototype.elementAt = function (index) { var element = this.elementAtOrDefault(index); if (element === undefined) { throw new Error("Out of bounds"); } return element; }; EnumerableBase.prototype.elementAtOrDefault = function (index) { if (index < 0) { throw new Error("Negative index is forbiden"); } this.reset(); var currentIndex = -1; while (this.next()) { ++currentIndex; if (currentIndex === index) { break; } } if (currentIndex !== index) { return undefined; } return this.value(); }; EnumerableBase.prototype.except = function (other) { return this.where(function (e) { return !other.contains(e); }); }; EnumerableBase.prototype.first = function (predicate) { var element; if (predicate !== undefined) { element = this.firstOrDefault(predicate); } else { element = this.firstOrDefault(); } if (element === undefined) { throw new Error("Sequence contains no elements"); } return element; }; EnumerableBase.prototype.firstOrDefault = function (predicate) { if (predicate !== undefined) { // Don't copy iterators return new ConditionalEnumerable(this, predicate).firstOrDefault(); } this.reset(); if (!this.next()) { return undefined; } return this.value(); }; EnumerableBase.prototype.forEach = function (action) { this.reset(); for (var i = 0; this.next(); ++i) { action(this.value(), i); } }; EnumerableBase.prototype.groupBy = function (keySelector, valueSelector) { var array = this.toArray(); var dictionary = new Collections_1.Dictionary(); for (var i = 0; i < array.length; ++i) { var key = keySelector(array[i]); var value = valueSelector !== undefined ? valueSelector(array[i]) : array[i]; if (!dictionary.containsKey(key)) { dictionary.set(key, new Collections_1.List()); } dictionary.get(key).push(value); } return dictionary.asEnumerable(); }; EnumerableBase.prototype.last = function (predicate) { var element; if (predicate !== undefined) { element = this.lastOrDefault(predicate); } else { element = this.lastOrDefault(); } if (element === undefined) { throw new Error("Sequence contains no elements"); } return element; }; EnumerableBase.prototype.lastOrDefault = function (predicate) { if (predicate !== undefined) { // Don't copy iterators return new ConditionalEnumerable(this, predicate).lastOrDefault(); } var reversed = new ReverseEnumerable(this); reversed.reset(); if (!reversed.next()) { return undefined; } return reversed.value(); }; EnumerableBase.prototype.single = function (predicate) { var element; if (predicate !== undefined) { element = this.singleOrDefault(predicate); } else { element = this.singleOrDefault(); } if (element === undefined) { throw new Error("Sequence contains no elements"); } return element; }; EnumerableBase.prototype.singleOrDefault = function (predicate) { if (predicate !== undefined) { // Don't copy iterators return new ConditionalEnumerable(this, predicate).singleOrDefault(); } this.reset(); if (!this.next()) { return undefined; } var element = this.value(); if (this.next()) { throw new Error("Sequence contains more than 1 element"); } return element; }; EnumerableBase.prototype.distinct = function (keySelector) { return new UniqueEnumerable(this.copy(), keySelector); }; EnumerableBase.prototype.aggregate = function (aggregator, initialValue) { var value = initialValue; this.reset(); if (initialValue === undefined) { if (!this.next()) { throw new Error("Sequence contains no elements"); } value = aggregator(value, this.value()); } while (this.next()) { value = aggregator(value, this.value()); } return value; }; EnumerableBase.prototype.min = function (selector) { if (selector !== undefined) { // Don't copy iterators return new TransformEnumerable(this, selector).min(); } return this.aggregate(function (previous, current) { return (previous !== undefined && previous < current) ? previous : current; }); }; EnumerableBase.prototype.orderBy = function (keySelector, comparer) { return new OrderedEnumerable(this.copy(), Comparers_1.createComparer(keySelector, true, comparer)); }; EnumerableBase.prototype.orderByDescending = function (keySelector) { return new OrderedEnumerable(this.copy(), Comparers_1.createComparer(keySelector, false, undefined)); }; EnumerableBase.prototype.max = function (selector) { if (selector !== undefined) { // Don't copy iterators return new TransformEnumerable(this, selector).max(); } return this.aggregate(function (previous, current) { return (previous !== undefined && previous > current) ? previous : current; }); }; EnumerableBase.prototype.sum = function (selector) { return this.aggregate(function (previous, current) { return previous + selector(current); }, 0); }; EnumerableBase.prototype.average = function (selector) { this.reset(); if (!this.next()) { throw new Error("Sequence contains no elements"); } var sum = 0; var count = 0; do { sum += selector(this.value()); ++count; } while (this.next()); return sum / count; }; EnumerableBase.prototype.skip = function (amount) { return new RangeEnumerable(this.copy(), amount, undefined); }; EnumerableBase.prototype.take = function (amount) { return new RangeEnumerable(this.copy(), undefined, amount); }; EnumerableBase.prototype.union = function (other) { return new UniqueEnumerable(this.concat(other)); }; return EnumerableBase; }()); exports.EnumerableBase = EnumerableBase; // endregion // region Enumerable var Enumerable = /** @class */ (function (_super) { __extends(Enumerable, _super); function Enumerable(source) { var _this = _super.call(this, source) || this; _this.currentValue = new Utils_1.Cached(); return _this; } Enumerable.fromSource = function (source) { if (Array.isArray(source)) { return new ArrayEnumerable(source); } return new Enumerable(source); }; Enumerable.empty = function () { return Enumerable.fromSource([]); }; Enumerable.range = function (start, count, ascending) { if (ascending === void 0) { ascending = true; } if (count < 0) { throw new Error("Count must be >= 0"); } var source = new Array(count); if (ascending) { // tslint:disable-next-line:curly for (var i = 0; i < count; source[i] = start + (i++)) ; } else { // tslint:disable-next-line:curly for (var i = 0; i < count; source[i] = start - (i++)) ; } return new ArrayEnumerable(source); }; Enumerable.repeat = function (element, count) { if (count < 0) { throw new Error("Count must me >= 0"); } var source = new Array(count); for (var i = 0; i < count; ++i) { source[i] = element; } return new ArrayEnumerable(source); }; Enumerable.prototype.copy = function () { return new Enumerable(this.source.copy()); }; Enumerable.prototype.value = function () { if (!this.currentValue.isValid()) { this.currentValue.value = this.source.value(); } return this.currentValue.value; }; Enumerable.prototype.reset = function () { _super.prototype.reset.call(this); this.currentValue.invalidate(); }; Enumerable.prototype.next = function () { this.currentValue.invalidate(); return _super.prototype.next.call(this); }; return Enumerable; }(EnumerableBase)); exports.Enumerable = Enumerable; // endregion // region ConditionalEnumerable var ConditionalEnumerable = /** @class */ (function (_super) { __extends(ConditionalEnumerable, _super); function ConditionalEnumerable(source, predicate) { var _this = _super.call(this, source) || this; _this._predicate = predicate; return _this; } ConditionalEnumerable.prototype.copy = function () { return new ConditionalEnumerable(this.source.copy(), this._predicate); }; ConditionalEnumerable.prototype.next = function () { var hasValue; do { hasValue = _super.prototype.next.call(this); } while (hasValue && !this._predicate(this.value())); return hasValue; }; return ConditionalEnumerable; }(Enumerable)); exports.ConditionalEnumerable = ConditionalEnumerable; // endregion // region ConcatEnumerable var ConcatEnumerable = /** @class */ (function (_super) { __extends(ConcatEnumerable, _super); function ConcatEnumerable(left, right) { var _this = _super.call(this, left) || this; _this._otherSource = right; _this._isFirstSourceFinished = false; return _this; } ConcatEnumerable.prototype.copy = function () { return new ConcatEnumerable(this.source.copy(), this._otherSource.copy()); }; ConcatEnumerable.prototype.reset = function () { this.source.reset(); this._otherSource.reset(); this._isFirstSourceFinished = false; this.currentValue.invalidate(); }; ConcatEnumerable.prototype.next = function () { this.currentValue.invalidate(); var hasValue = !this._isFirstSourceFinished ? this.source.next() : this._otherSource.next(); if (!hasValue && !this._isFirstSourceFinished) { this._isFirstSourceFinished = true; return this.next(); } return hasValue; }; ConcatEnumerable.prototype.value = function () { if (!this.currentValue.isValid()) { this.currentValue.value = !this._isFirstSourceFinished ? this.source.value() : this._otherSource.value(); } return this.currentValue.value; }; return ConcatEnumerable; }(Enumerable)); exports.ConcatEnumerable = ConcatEnumerable; // endregion // region UniqueEnumerable var UniqueEnumerable = /** @class */ (function (_super) { __extends(UniqueEnumerable, _super); function UniqueEnumerable(source, keySelector) { var _this = _super.call(this, source) || this; _this._keySelector = keySelector; _this._seen = { primitive: { number: {}, string: {}, boolean: {} }, complex: [] }; return _this; } UniqueEnumerable.prototype.copy = function () { return new UniqueEnumerable(this.source.copy(), this._keySelector); }; UniqueEnumerable.prototype.reset = function () { _super.prototype.reset.call(this); this._seen = { primitive: { number: {}, string: {}, boolean: {} }, complex: [] }; }; UniqueEnumerable.prototype.isUnique = function (element) { var key = this._keySelector !== undefined ? this._keySelector(element) : element; var type = typeof key; return (type in this._seen.primitive) ? this._seen.primitive[type].hasOwnProperty(key) ? false : this._seen.primitive[type][key] = true : this._seen.complex.indexOf(key) !== -1 ? false : this._seen.complex.push(key) > -1; }; UniqueEnumerable.prototype.next = function () { var hasValue; do { hasValue = _super.prototype.next.call(this); } while (hasValue && !this.isUnique(this.value())); return hasValue; }; return UniqueEnumerable; }(Enumerable)); exports.UniqueEnumerable = UniqueEnumerable; // endregion // region RangeEnumerable var RangeEnumerable = /** @class */ (function (_super) { __extends(RangeEnumerable, _super); function RangeEnumerable(source, start, count) { var _this = this; if ((start !== undefined && start < 0) || (count !== undefined && count < 0)) { throw new Error("Incorrect parameters"); } _this = _super.call(this, source) || this; _this._start = start; _this._count = count; _this._currentIndex = -1; return _this; } RangeEnumerable.prototype.copy = function () { return new RangeEnumerable(this.source.copy(), this._start, this._count); }; RangeEnumerable.prototype.reset = function () { _super.prototype.reset.call(this); this._currentIndex = -1; }; RangeEnumerable.prototype.isValidIndex = function () { var start = this._start !== undefined ? this._start : 0; var end = this._count !== undefined ? start + this._count : undefined; return this._currentIndex >= start && (end === undefined || this._currentIndex < end); }; RangeEnumerable.prototype.performSkip = function () { var start = this._start !== undefined ? this._start : 0; var hasValue = true; while (hasValue && this._currentIndex + 1 < start) { hasValue = _super.prototype.next.call(this); ++this._currentIndex; } return hasValue; }; RangeEnumerable.prototype.next = function () { if (this._currentIndex < 0 && !this.performSkip()) { return false; } ++this._currentIndex; return _super.prototype.next.call(this) && this.isValidIndex(); }; RangeEnumerable.prototype.value = function () { if (!this.isValidIndex()) { throw new Error("Out of bounds"); } return _super.prototype.value.call(this); }; return RangeEnumerable; }(Enumerable)); exports.RangeEnumerable = RangeEnumerable; // endregion // region TransformEnumerable var TransformEnumerable = /** @class */ (function (_super) { __extends(TransformEnumerable, _super); function TransformEnumerable(source, transform) { var _this = _super.call(this, source) || this; _this._transform = transform; _this._currentValue = new Utils_1.Cached(); return _this; } TransformEnumerable.prototype.copy = function () { return new TransformEnumerable(this.source.copy(), this._transform); }; TransformEnumerable.prototype.value = function () { if (!this._currentValue.isValid()) { this._currentValue.value = this._transform(this.source.value()); } return this._currentValue.value; }; TransformEnumerable.prototype.reset = function () { _super.prototype.reset.call(this); this._currentValue.invalidate(); }; TransformEnumerable.prototype.next = function () { this._currentValue.invalidate(); return _super.prototype.next.call(this); }; return TransformEnumerable; }(EnumerableBase)); exports.TransformEnumerable = TransformEnumerable; // endregion // region ReverseEnumerable var ReverseEnumerable = /** @class */ (function (_super) { __extends(ReverseEnumerable, _super); function ReverseEnumerable(source) { var _this = _super.call(this, source) || this; _this._elements = new Utils_1.Cached(); _this._currentIndex = -1; return _this; } ReverseEnumerable.prototype.copy = function () { return new ReverseEnumerable(this.source.copy()); }; ReverseEnumerable.prototype.reset = function () { this._elements.invalidate(); this._currentIndex = -1; }; ReverseEnumerable.prototype.isValidIndex = function () { return this._currentIndex >= 0 && this._currentIndex < this._elements.value.length; }; ReverseEnumerable.prototype.all = function (predicate) { return this.source.all(predicate); }; ReverseEnumerable.prototype.any = function (predicate) { if (predicate !== undefined) { return this.source.any(predicate); } return this.source.any(); }; ReverseEnumerable.prototype.average = function (selector) { return this.source.average(selector); }; ReverseEnumerable.prototype.count = function (predicate) { if (predicate !== undefined) { return this.source.count(predicate); } return this.source.count(); }; ReverseEnumerable.prototype.max = function (selector) { if (selector !== undefined) { return this.source.max(selector); } return this.source.max(); }; ReverseEnumerable.prototype.min = function (selector) { if (selector !== undefined) { return this.source.min(selector); } return this.source.min(); }; ReverseEnumerable.prototype.reverse = function () { return this.source.copy(); // haha so smart }; ReverseEnumerable.prototype.sum = function (selector) { return this.source.sum(selector); }; ReverseEnumerable.prototype.next = function () { if (!this._elements.isValid()) { this._elements.value = this.source.toArray(); } ++this._currentIndex; return this.isValidIndex(); }; ReverseEnumerable.prototype.value = function () { if (!this._elements.isValid() || !this.isValidIndex()) { throw new Error("Out of bounds"); } return this._elements.value[(this._elements.value.length - 1) - this._currentIndex]; }; return ReverseEnumerable; }(Enumerable)); exports.ReverseEnumerable = ReverseEnumerable; // endregion // region OrderedEnumerable var OrderedEnumerable = /** @class */ (function (_super) { __extends(OrderedEnumerable, _super); function OrderedEnumerable(source, comparer) { var _this = _super.call(this, source) || this; _this._comparer = comparer; _this._elements = new Utils_1.Cached(); _this._currentIndex = -1; return _this; } OrderedEnumerable.prototype.isValidIndex = function () { return this._currentIndex >= 0 && this._currentIndex < this._elements.value.length; }; OrderedEnumerable.prototype.orderBy = function (keySelector, comparer) { return new OrderedEnumerable(this.source.copy(), Comparers_1.createComparer(keySelector, true, comparer)); }; OrderedEnumerable.prototype.orderByDescending = function (keySelector) { return new OrderedEnumerable(this.source.copy(), Comparers_1.createComparer(keySelector, false, undefined)); }; OrderedEnumerable.prototype.thenBy = function (keySelector, comparer) { return new OrderedEnumerable(this.source.copy(), Comparers_1.combineComparers(this._comparer, Comparers_1.createComparer(keySelector, true, comparer))); }; OrderedEnumerable.prototype.thenByDescending = function (keySelector) { return new OrderedEnumerable(this.source.copy(), Comparers_1.combineComparers(this._comparer, Comparers_1.createComparer(keySelector, false, undefined))); }; OrderedEnumerable.prototype.reset = function () { this._elements.invalidate(); this._currentIndex = -1; }; OrderedEnumerable.prototype.copy = function () { return new OrderedEnumerable(this.source.copy(), this._comparer); }; OrderedEnumerable.prototype.value = function () { if (!this._elements.isValid() || !this.isValidIndex()) { throw new Error("Out of bounds"); } return this._elements.value[this._currentIndex]; }; OrderedEnumerable.prototype.next = function () { if (!this._elements.isValid()) { this._elements.value = this.toArray(); } ++this._currentIndex; return this.isValidIndex(); }; OrderedEnumerable.prototype.toArray = function () { // Allocate the array before sorting // It's faster than working with anonymous reference var result = this.source.toArray(); return result.sort(this._comparer); }; return OrderedEnumerable; }(EnumerableBase)); exports.OrderedEnumerable = OrderedEnumerable; // endregion // region ArrayEnumerable var ArrayEnumerable = /** @class */ (function (_super) { __extends(ArrayEnumerable, _super); function ArrayEnumerable(source) { var _this = _super.call(this, new Iterators_1.ArrayIterator(source)) || this; _this.list = new Collections_1.List(source); return _this; } ArrayEnumerable.prototype.toArray = function () { return this.list.toArray(); }; ArrayEnumerable.prototype.aggregate = function (aggregator, initialValue) { if (initialValue !== undefined) { return this.list.aggregate(aggregator, initialValue); } return this.list.aggregate(aggregator); }; ArrayEnumerable.prototype.any = function (predicate) { if (predicate !== undefined) { return this.list.any(predicate); } return this.list.any(); }; ArrayEnumerable.prototype.all = function (predicate) { return this.list.all(predicate); }; ArrayEnumerable.prototype.average = function (selector) { return this.list.average(selector); }; ArrayEnumerable.prototype.count = function (predicate) { if (predicate !== undefined) { return this.list.count(predicate); } return this.list.count(); }; ArrayEnumerable.prototype.copy = function () { return new ArrayEnumerable(this.list.asArray()); }; ArrayEnumerable.prototype.elementAtOrDefault = function (index) { return this.list.elementAtOrDefault(index); }; ArrayEnumerable.prototype.firstOrDefault = function (predicate) { if (predicate !== undefined) { return this.list.firstOrDefault(predicate); } return this.list.firstOrDefault(); }; ArrayEnumerable.prototype.lastOrDefault = function (predicate) { if (predicate !== undefined) { return this.list.lastOrDefault(predicate); } return this.list.lastOrDefault(); }; return ArrayEnumerable; }(Enumerable)); exports.ArrayEnumerable = ArrayEnumerable; // endregion //# sourceMappingURL=Enumerables.js.map