linqts
Version:
LinQ + TypeScript
733 lines • 29.5 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
import { composeComparers, isObj, equal, keyComparer } from './helpers.js';
var List = /** @class */ (function () {
/**
* Defaults the elements of the list
*/
function List(elements) {
if (elements === void 0) { elements = []; }
this._elements = __spreadArray([], __read(elements), false);
}
/**
* Make the List iterable and Spreadable
*/
List.prototype[Symbol.iterator] = function () {
var _a, _b, element, e_1_1;
var e_1, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
_d.trys.push([0, 5, 6, 7]);
_a = __values(this._elements), _b = _a.next();
_d.label = 1;
case 1:
if (!!_b.done) return [3 /*break*/, 4];
element = _b.value;
return [4 /*yield*/, element];
case 2:
_d.sent();
_d.label = 3;
case 3:
_b = _a.next();
return [3 /*break*/, 1];
case 4: return [3 /*break*/, 7];
case 5:
e_1_1 = _d.sent();
e_1 = { error: e_1_1 };
return [3 /*break*/, 7];
case 6:
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_1) throw e_1.error; }
return [7 /*endfinally*/];
case 7: return [2 /*return*/];
}
});
};
Object.defineProperty(List.prototype, Symbol.toStringTag, {
/**
* property represents the Object name
*/
get: function () {
return 'List'; // Expected output: "[object List]"
},
enumerable: false,
configurable: true
});
/**
* Adds an object to the end of the List<T>.
*/
List.prototype.Add = function (element) {
this._elements.push(element);
};
/**
* Appends an object to the end of the List<T>.
*/
List.prototype.Append = function (element) {
this.Add(element);
};
/**
* Add an object to the start of the List<T>.
*/
List.prototype.Prepend = function (element) {
this._elements.unshift(element);
};
/**
* Adds the elements of the specified collection to the end of the List<T>.
*/
List.prototype.AddRange = function (elements) {
var _a;
(_a = this._elements).push.apply(_a, __spreadArray([], __read(elements), false));
};
/**
* Applies an accumulator function over a sequence.
*/
List.prototype.Aggregate = function (accumulator, initialValue) {
return this._elements.reduce(accumulator, initialValue);
};
/**
* Determines whether all elements of a sequence satisfy a condition.
*/
List.prototype.All = function (predicate) {
return this._elements.every(predicate);
};
/**
* Determines whether a sequence contains any elements.
*/
List.prototype.Any = function (predicate) {
return predicate
? this._elements.some(predicate)
: this._elements.length > 0;
};
/**
* Computes the average of a sequence of number values that are obtained by invoking
* a transform function on each element of the input sequence.
*/
List.prototype.Average = function (transform) {
return this.Sum(transform) / this.Count(transform);
};
/**
* Casts the elements of a sequence to the specified type.
*/
List.prototype.Cast = function () {
return new List(this._elements);
};
/**
* Removes all elements from the List<T>.
*/
List.prototype.Clear = function () {
this._elements.length = 0;
};
/**
* Concatenates two sequences.
*/
List.prototype.Concat = function (list) {
return new List(this._elements.concat(list.ToArray()));
};
/**
* Determines whether an element is in the List<T>.
*/
List.prototype.Contains = function (element) {
return this.Any(function (x) { return x === element; });
};
/**
* Returns the number of elements in a sequence.
*/
List.prototype.Count = function (predicate) {
return predicate ? this.Where(predicate).Count() : this._elements.length;
};
/**
* Returns the elements of the specified sequence or the type parameter's default value
* in a singleton collection if the sequence is empty.
*/
List.prototype.DefaultIfEmpty = function (defaultValue) {
return this.Count() ? this : new List([defaultValue]);
};
/**
* Returns distinct elements from a sequence by using the default equality comparer to compare values.
*/
List.prototype.Distinct = function () {
return this.Where(function (value, index, iter) {
return (isObj(value)
? iter &&
iter.findIndex(function (obj) {
return equal(obj, value);
})
: iter && iter.indexOf(value)) === index;
});
};
/**
* Returns distinct elements from a sequence according to specified key selector.
*/
List.prototype.DistinctBy = function (keySelector) {
var groups = this.GroupBy(keySelector);
return Object.keys(groups).reduce(function (res, key) {
var _a;
var firstElement = (_a = groups === null || groups === void 0 ? void 0 : groups[key]) === null || _a === void 0 ? void 0 : _a[0];
if (firstElement !== undefined) {
res.Add(firstElement);
}
return res;
}, new List());
};
/**
* Returns the element at a specified index in a sequence.
*/
List.prototype.ElementAt = function (index) {
if (index < this.Count() && index >= 0) {
return this._elements[index];
}
throw new Error('ArgumentOutOfRangeException: index is less than 0 or greater than or equal to the number of elements in source.');
};
/**
* Returns the element at a specified index in a sequence or a default value if the index is out of range.
*/
List.prototype.ElementAtOrDefault = function (index) {
var _a;
return index < this.Count() && index >= 0
? (_a = this._elements[index]) !== null && _a !== void 0 ? _a : null
: null;
};
/**
* Produces the set difference of two sequences by using the default equality comparer to compare values.
*/
List.prototype.Except = function (source) {
return this.Where(function (x) { return !source.Contains(x); });
};
/**
* Returns the first element of a sequence.
*/
List.prototype.First = function (predicate) {
if (this.Count()) {
return predicate ? this.Where(predicate).First() : this._elements[0];
}
throw new Error('InvalidOperationException: The source sequence is empty.');
};
/**
* Returns the first element of a sequence, or a default value if the sequence contains no elements.
*/
List.prototype.FirstOrDefault = function (defaultValue) {
return this.Count() ? this.First() : defaultValue;
};
/**
* Performs the specified action on each element of the List<T>.
*/
List.prototype.ForEach = function (action) {
return this._elements.forEach(action);
};
/**
* Groups the elements of a sequence according to a specified key selector function.
*/
List.prototype.GroupBy = function (grouper, mapper) {
if (mapper === void 0) { mapper = function (val) { return val; }; }
var initialValue = {};
return this.Aggregate(function (ac, v) {
var key = grouper(v);
var existingGroup = isObj(ac) && ac[key];
var mappedValue = mapper(v);
if (!!existingGroup) {
existingGroup.push(mappedValue);
}
else {
;
ac[key] = [mappedValue];
}
return ac;
}, initialValue);
};
/**
* Correlates the elements of two sequences based on equality of keys and groups the results.
* The default equality comparer is used to compare keys.
*/
List.prototype.GroupJoin = function (list, key1, key2, result) {
return this.Select(function (x) {
return result(x, list.Where(function (z) { return key1(x) === key2(z); }));
});
};
/**
* Returns the index of the first occurence of an element in the List.
*/
List.prototype.IndexOf = function (element) {
return this._elements.indexOf(element);
};
/**
* Inserts an element into the List<T> at the specified index.
*/
List.prototype.Insert = function (index, element) {
if (index < 0 || index > this._elements.length) {
throw new Error('Index is out of range.');
}
this._elements.splice(index, 0, element);
};
/**
* Produces the set intersection of two sequences by using the default equality comparer to compare values.
*/
List.prototype.Intersect = function (source) {
return this.Where(function (x) { return source.Contains(x); });
};
/**
* Correlates the elements of two sequences based on matching keys. The default equality comparer is used to compare keys.
*/
List.prototype.Join = function (list, key1, key2, result) {
return this.SelectMany(function (x) {
return list.Where(function (y) { return key2(y) === key1(x); }).Select(function (z) { return result(x, z); });
});
};
/**
* Returns the last element of a sequence.
*/
List.prototype.Last = function (predicate) {
if (this.Count()) {
return predicate
? this.Where(predicate).Last()
: this._elements[this.Count() - 1];
}
throw Error('InvalidOperationException: The source sequence is empty.');
};
/**
* Returns the last element of a sequence, or a default value if the sequence contains no elements.
*/
List.prototype.LastOrDefault = function (defaultValue) {
return this.Count() ? this.Last() : defaultValue;
};
/**
* Retrieves a default comparer function based on the type of the provided sample value.
* Only supports primitive types: number, string, and boolean.
*
* @param sample - A sample value used to determine its type.
* @returns A comparison function suitable for the type of the sample, or undefined if unsupported.
*/
List.getComparer = function (sample) {
var type = typeof sample;
return List.comparers.get(type);
};
/**
* Gets the maximum value in a generic sequence.
* @returns The maximum value in the sequence, or undefined if the sequence is empty.
* @param comparerOrSelector - An optional custom comparison function or a selector function to select a value from each element for comparison.
*/
List.prototype.Max = function (comparerOrSelector) {
if (this._elements.length === 0)
return undefined;
if (!comparerOrSelector) {
// Max(): T | undefined;
return this.getMaxElement(this._elements);
}
var fn = comparerOrSelector;
if (!fn || fn.length > 2 || fn.length === 0) {
throw new Error('InvalidOperationException: Invalid comparer or selector function provided.');
}
if (fn.length === 1) {
// Max<R>(selector: (e: T) => R): R | undefined;
return this.getMaxElement(this._elements.map(fn));
}
//fn.length === 2
// Max(comparer: (a: T, b: T) => number): T | undefined;
return this.getMaxElement(this._elements, fn);
};
/**
* Returns the maximum value in a generic sequence.
* @param elements - The array of elements to find the maximum from.
* @param customComparer - An optional custom comparison function.
*/
List.prototype.getMaxElement = function (elements, customComparer) {
if (elements.length === 0) {
throw new Error('InvalidOperationException: Sequence contains no elements.');
}
var comparerToUse = customComparer !== null && customComparer !== void 0 ? customComparer : List.getComparer(elements[0]);
if (!comparerToUse) {
throw new Error('InvalidOperationException: No comparer available.');
}
return elements.reduce(function (currentMax, elem) {
return comparerToUse(elem, currentMax) > 0 ? elem : currentMax;
}, elements[0]);
};
/**
* Gets the minimum value in a generic sequence.
* @returns The minimum value in the sequence, or undefined if the sequence is empty.
* @param comparerOrSelector - An optional custom comparison function or a selector function to select a value from each element for comparison.
*/
List.prototype.Min = function (comparerOrSelector) {
if (this._elements.length === 0)
return undefined;
if (!comparerOrSelector) {
// Min(): T | undefined;
return this.getMinElement(this._elements);
}
var fn = comparerOrSelector;
if (!fn || fn.length > 2 || fn.length === 0) {
throw new Error('InvalidOperationException: Invalid comparer or selector function provided.');
}
if (fn.length === 1) {
// Min<R>(selector: (e: T) => R): R | undefined;
return this.getMinElement(this._elements.map(fn));
}
//fn.length === 2
// Min(comparer: (a: T, b: T) => number): T | undefined;
return this.getMinElement(this._elements, fn);
};
/**
* Returns the minimum value in a generic sequence.
* @param elements - The array of elements to find the minimum from.
* @param customComparer - An optional custom comparison function.
*/
List.prototype.getMinElement = function (elements, customComparer) {
if (elements.length === 0) {
throw new Error('InvalidOperationException: Sequence contains no elements.');
}
var comparerToUse = customComparer !== null && customComparer !== void 0 ? customComparer : List.getComparer(elements[0]);
if (!comparerToUse) {
throw new Error('InvalidOperationException: No comparer available.');
}
return elements.reduce(function (currentMin, elem) {
return comparerToUse(elem, currentMin) < 0 ? elem : currentMin;
}, elements[0]);
};
/**
* Filters the elements of a sequence based on a specified type.
*/
List.prototype.OfType = function (type) {
var typeName;
switch (type) {
case Number:
typeName = typeof 0;
break;
case String:
typeName = typeof '';
break;
case Boolean:
typeName = typeof true;
break;
case Function:
typeName = typeof function () { }; // tslint:disable-line no-empty
break;
default:
typeName = null;
break;
}
return typeName === null
? this.Where(function (x) { return x instanceof type; }).Cast()
: this.Where(function (x) { return typeof x === typeName; }).Cast();
};
/**
* Sorts the elements of a sequence in ascending order according to a key.
*/
List.prototype.OrderBy = function (keySelector, comparer) {
if (comparer === void 0) { comparer = keyComparer(keySelector, false); }
// tslint:disable-next-line: no-use-before-declare
return new OrderedList(this._elements, comparer);
};
/**
* Sorts the elements of a sequence in descending order according to a key.
*/
List.prototype.OrderByDescending = function (keySelector, comparer) {
if (comparer === void 0) { comparer = keyComparer(keySelector, true); }
// tslint:disable-next-line: no-use-before-declare
return new OrderedList(this._elements, comparer);
};
/**
* Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
*/
List.prototype.ThenBy = function (keySelector) {
return this.OrderBy(keySelector);
};
/**
* Performs a subsequent ordering of the elements in a sequence in descending order, according to a key.
*/
List.prototype.ThenByDescending = function (keySelector) {
return this.OrderByDescending(keySelector);
};
/**
* Removes the first occurrence of a specific object from the List<T>.
*/
List.prototype.Remove = function (element) {
return this.IndexOf(element) !== -1
? (this.RemoveAt(this.IndexOf(element)), true)
: false;
};
/**
* Removes all the elements that match the conditions defined by the specified predicate.
*/
List.prototype.RemoveAll = function (predicate) {
return this.Where(function (value, index, list) { return !predicate(value, index, list); });
};
/**
* Removes the element at the specified index of the List<T>.
*/
List.prototype.RemoveAt = function (index) {
this._elements.splice(index, 1);
};
/**
* Reverses the order of the elements in the entire List<T>.
*/
List.prototype.Reverse = function () {
return new List(this._elements.reverse());
};
/**
* Projects each element of a sequence into a new form.
*/
List.prototype.Select = function (selector) {
return new List(this._elements.map(selector));
};
/**
* Projects each element of a sequence to a List<any> and flattens the resulting sequences into one sequence.
*/
List.prototype.SelectMany = function (selector) {
var _this = this;
return this.Aggregate(function (ac, _, i) { return (ac.AddRange(_this.Select(selector)
.ElementAt(i)
.ToArray()),
ac); }, new List());
};
/**
* Determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.
*/
List.prototype.SequenceEqual = function (list) {
return this.All(function (e) { return list.Contains(e); });
};
/**
* Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.
*/
List.prototype.Single = function (predicate) {
if (this.Count(predicate) !== 1) {
throw new Error('The collection does not contain exactly one element.');
}
return this.First(predicate);
};
/**
* Returns the only element of a sequence, or a default value if the sequence is empty;
* this method throws an exception if there is more than one element in the sequence.
*/
List.prototype.SingleOrDefault = function (defaultValue) {
return this.Count() ? this.Single() : defaultValue;
};
/**
* Bypasses a specified number of elements in a sequence and then returns the remaining elements.
*/
List.prototype.Skip = function (amount) {
return new List(this._elements.slice(Math.max(0, amount)));
};
/**
* Omit the last specified number of elements in a sequence and then returns the remaining elements.
*/
List.prototype.SkipLast = function (amount) {
return new List(this._elements.slice(0, -Math.max(0, amount)));
};
/**
* Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.
*/
List.prototype.SkipWhile = function (predicate) {
var _this = this;
return this.Skip(this.Aggregate(function (ac) { return (predicate(_this.ElementAt(ac)) ? ++ac : ac); }, 0));
};
/**
* Computes the sum of the sequence of number values that are obtained by invoking
* a transform function on each element of the input sequence.
*/
List.prototype.Sum = function (transform) {
return transform
? this.Select(transform).Sum()
: this.Aggregate(function (ac, v) { return (ac += +v); }, 0);
};
/**
* Returns a specified number of contiguous elements from the start of a sequence.
*/
List.prototype.Take = function (amount) {
return new List(this._elements.slice(0, Math.max(0, amount)));
};
/**
* Returns a specified number of contiguous elements from the end of a sequence.
*/
List.prototype.TakeLast = function (amount) {
return new List(this._elements.slice(-Math.max(0, amount)));
};
/**
* Returns elements from a sequence as long as a specified condition is true.
*/
List.prototype.TakeWhile = function (predicate) {
var _this = this;
return this.Take(this.Aggregate(function (ac) { return (predicate(_this.ElementAt(ac)) ? ++ac : ac); }, 0));
};
/**
* Copies the elements of the List<T> to a new array.
*/
List.prototype.ToArray = function () {
return this._elements;
};
/**
* Creates a Dictionary<TKey, TValue> from a List<T> according to a specified key selector function.
*/
List.prototype.ToDictionary = function (key, value) {
var _this = this;
return this.Aggregate(function (dicc, v, i) {
// const dictionaryKey = String(this.Select(key).ElementAt(i))
// ;((dicc as unknown) as Record<string, T | TValue>)[dictionaryKey] = value
// ? this.Select(value).ElementAt(i)
// : v
dicc.Add({
Key: _this.Select(key).ElementAt(i),
Value: !!value ? _this.Select(value).ElementAt(i) : v
});
return dicc;
}, new List());
};
/**
* Creates a List<T> from an Enumerable.List<T>.
*/
List.prototype.ToList = function () {
return this;
};
/**
* Creates a Lookup<TKey, TElement> from an IEnumerable<T> according to specified key selector and element selector functions.
*/
List.prototype.ToLookup = function (keySelector, elementSelector) {
return this.GroupBy(keySelector, elementSelector);
};
/**
* Produces the set union of two sequences by using the default equality comparer.
*/
List.prototype.Union = function (list) {
return this.Concat(list).Distinct();
};
/**
* Filters a sequence of values based on a predicate.
*/
List.prototype.Where = function (predicate) {
return new List(this._elements.filter(predicate));
};
/**
* Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.
*/
List.prototype.Zip = function (list, result) {
var _this = this;
return list.Count() < this.Count()
? list.Select(function (x, y) { return result(_this.ElementAt(y), x); })
: this.Select(function (x, y) { return result(x, list.ElementAt(y)); });
};
// A map of built-in primitive type names to their default comparison functions.
// This supports number, string, and boolean only
List.comparers = new Map([
['number', function (a, b) { return a - b; }],
['string', function (a, b) { return a.localeCompare(b); }],
['boolean', function (a, b) { return Number(a) - Number(b); }]
]);
return List;
}());
/**
* Represents a sorted sequence. The methods of this class are implemented by using deferred execution.
* The immediate return value is an object that stores all the information that is required to perform the action.
* The query represented by this method is not executed until the object is enumerated either by
* calling its ToDictionary, ToLookup, ToList or ToArray methods
*/
var OrderedList = /** @class */ (function (_super) {
__extends(OrderedList, _super);
function OrderedList(elements, _comparer) {
var _this = _super.call(this, elements) || this;
_this._comparer = _comparer;
_this._elements.sort(_this._comparer);
return _this;
}
/**
* Allows you to get the parent List out of the OrderedList
* @override
* @returns and ordered list turned into a regular List<T>
*/
OrderedList.prototype.ToList = function () {
return new List(this._elements);
};
/**
* Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
* @override
*/
OrderedList.prototype.ThenBy = function (keySelector) {
return new OrderedList(this._elements, composeComparers(this._comparer, keyComparer(keySelector, false)));
};
/**
* Performs a subsequent ordering of the elements in a sequence in descending order, according to a key.
* @override
*/
OrderedList.prototype.ThenByDescending = function (keySelector) {
return new OrderedList(this._elements, composeComparers(this._comparer, keyComparer(keySelector, true)));
};
return OrderedList;
}(List));
export default List;
//# sourceMappingURL=list.js.map