nativescript-enumerable
Version:
A NativeScript module providing LINQ style extensions for handling arrays and lists.
1,440 lines • 46.1 kB
JavaScript
// The MIT License (MIT)
//
// Copyright (c) Marcel Joachim Kloubert <marcel.kloubert@gmx.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
"use strict";
var observable_1 = require("data/observable");
var observable_array_1 = require("data/observable-array");
var TypeUtils = require("utils/types");
var virtual_array_1 = require("data/virtual-array");
/**
* Regular expression for trimming a string
* at the beginning and the end.
*/
exports.REGEX_TRIM = /^\s+|\s+$/gm;
/**
* A basic sequence.
*/
var Sequence = (function () {
function Sequence() {
}
/** @inheritdoc */
Sequence.prototype.aggregate = function (accumulator, defaultValue) {
var acc = asFunc(accumulator);
var index = -1;
var aggResult = defaultValue;
var isFirst = true;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (!isFirst) {
aggResult = acc(aggResult, ctx.item, ctx.index, ctx);
}
else {
aggResult = ctx.item;
isFirst = false;
}
if (ctx.cancel) {
break;
}
}
return aggResult;
};
/** @inheritdoc */
Sequence.prototype.all = function (predicate) {
predicate = asFunc(predicate);
var index = -1;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (!predicate(ctx.item, ctx.index, ctx)) {
return false;
}
if (ctx.cancel) {
break;
}
}
return true;
};
/** @inheritdoc */
Sequence.prototype.any = function (predicate) {
predicate = toPredicateSafe(predicate);
var index = -1;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (predicate(ctx.item, ctx.index, ctx)) {
return true;
}
if (ctx.cancel) {
break;
}
}
return false;
};
/** @inheritdoc */
Sequence.prototype.average = function (defaultValue) {
var cnt = 0;
var sum = 0;
while (this.moveNext()) {
sum += parseFloat("" + this.current);
++cnt;
}
return cnt > 0 ? (sum / cnt)
: defaultValue;
};
/** @inheritdoc */
Sequence.prototype.cast = function (type) {
if (type !== null) {
if (TypeUtils.isUndefined(type)) {
type = '';
}
else {
type = type.replace(exports.REGEX_TRIM, '');
}
}
return this.select(function (x) {
if (typeof x === type) {
return x;
}
if (type === null) {
return null;
}
switch (type) {
case '':
return x;
case 'null':
return null;
case 'undefined':
return undefined;
case 'number':
if (!x) {
return 0.0;
}
if (!isNaN(x)) {
return x;
}
return parseFloat(x);
case 'float':
if (!x) {
return 0.0;
}
return parseFloat(x);
case 'int':
case 'integer':
if (!x) {
return 0;
}
return parseInt(x);
case 'str':
case 'string':
if (!x) {
return "";
}
return "" + x;
case 'enumerable':
case 'seq':
case 'sequence':
return asEnumerable(x);
case 'array':
case 'Array':
return asEnumerable(x).toArray();
case 'Observable':
case 'observable':
return asEnumerable(x).toObservable();
case 'observablearray':
case 'observableArray':
case 'ObservableArray':
return asEnumerable(x).toObservableArray();
case 'bool':
case 'boolean':
return x ? true : false;
case 'func':
case 'function':
return function () { return x; };
default:
throw "Cannot not cast '" + x + "' to '" + type + "'!";
}
});
};
/** @inheritdoc */
Sequence.prototype.concat = function (second) {
var newItems = [];
var appendItems = function (seq) {
while (seq.moveNext()) {
newItems.push(seq.current);
}
};
appendItems(this);
appendItems(asEnumerable(second));
return fromArray(newItems);
};
/** @inheritdoc */
Sequence.prototype.contains = function (item, equalityComparer) {
equalityComparer = toEqualityComparerSafe(equalityComparer);
return this.any(function (x) { return equalityComparer(x, item); });
};
/** @inheritdoc */
Sequence.prototype.count = function (predicate) {
predicate = toPredicateSafe(predicate);
var index = -1;
var cnt = 0;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (predicate(ctx.item, ctx.index, ctx)) {
++cnt;
}
if (ctx.cancel) {
break;
}
}
return cnt;
};
Object.defineProperty(Sequence.prototype, "current", {
/** @inheritdoc */
get: function () {
return this.selectInner(this.getCurrent());
},
enumerable: true,
configurable: true
});
/** @inheritdoc */
Sequence.prototype.defaultIfEmpty = function () {
var defaultItems = [];
for (var _i = 0; _i < arguments.length; _i++) {
defaultItems[_i - 0] = arguments[_i];
}
if (!this.isValid) {
return fromArray(arguments);
}
return this;
};
/** @inheritdoc */
Sequence.prototype.distinct = function (equalityComparer) {
equalityComparer = toEqualityComparerSafe(equalityComparer);
var distinctedItems = [];
while (this.moveNext()) {
var curItem = this.current;
var alreadyInList = false;
for (var i = 0; i < distinctedItems.length; i++) {
if (equalityComparer(curItem, distinctedItems[i])) {
alreadyInList = true;
break;
}
}
if (!alreadyInList) {
distinctedItems.push(curItem);
}
}
return fromArray(distinctedItems);
};
/** @inheritdoc */
Sequence.prototype.each = function (action) {
action = asFunc(action);
var index = -1;
var result;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
result = action(ctx.item, ctx.index, ctx);
if (ctx.cancel) {
break;
}
}
return result;
};
/** @inheritdoc */
Sequence.prototype.elementAt = function (index) {
return this.first(function (x, i) {
return i == index;
});
};
/** @inheritdoc */
Sequence.prototype.elementAtOrDefault = function (index, defaultValue) {
return this.firstOrDefault(function (x, i) {
return i == index;
}, defaultValue);
};
/** @inheritdoc */
Sequence.prototype.except = function (second, equalityComparer) {
var ec = toEqualityComparerSafe(equalityComparer);
second = asEnumerable(second).distinct(ec)
.toArray();
var newItems = [];
while (this.moveNext()) {
var curItem = this.current;
var found = false;
for (var i = 0; i < second.length; i++) {
var secondItem = second[i];
if (ec(curItem, secondItem)) {
found = true;
break;
}
}
if (!found) {
newItems.push(curItem);
}
}
return fromArray(newItems);
};
/** @inheritdoc */
Sequence.prototype.first = function (predicate) {
predicate = toPredicateSafe(predicate);
var index = -1;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (predicate(ctx.item, ctx.index, ctx)) {
return ctx.item;
}
if (ctx.cancel) {
break;
}
}
throw "Sequence contains NO element!";
};
/** @inheritdoc */
Sequence.prototype.firstOrDefault = function (predicateOrDefaultValue, defaultValue) {
var odObj = createObjectForOrDefaultMethod(arguments);
var index = -1;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (odObj.predicate(ctx.item, ctx.index, ctx)) {
return ctx.item;
}
if (ctx.cancel) {
break;
}
}
return odObj.defaultValue;
};
/** @inheritdoc */
Sequence.prototype.groupBy = function (keySelector, keyEqualityComparer) {
var ks = asFunc(keySelector);
var kc = toEqualityComparerSafe(keyEqualityComparer);
var index = -1;
var groupList = [];
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
var key = ks(ctx.item, ctx.index, ctx);
var grp = null;
for (var i = 0; i < groupList.length; i++) {
var g = groupList[i];
if (kc(g.key, key)) {
grp = g;
break;
}
}
if (null === grp) {
grp = {
key: key,
values: []
};
groupList.push(grp);
}
grp.values.push(ctx.item);
if (ctx.cancel) {
break;
}
}
return fromArray(groupList.map(function (x) {
return new Grouping(x.key, asEnumerable(x.values));
}));
};
/** @inheritdoc */
Sequence.prototype.groupJoin = function (inner, outerKeySelector, innerKeySelector, resultSelector, keyEqualityComparer) {
inner = asEnumerable(inner);
var rc = asFunc(resultSelector);
var kc = toEqualityComparerSafe(keyEqualityComparer);
var createGroupsForSequence = function (seq, keySelector) {
return seq.groupBy(keySelector)
.select(function (grouping) {
return {
key: grouping.key,
values: grouping.toArray()
};
})
.toArray();
};
var outerGroups = createGroupsForSequence(this, outerKeySelector);
var innerGroups = createGroupsForSequence(inner, innerKeySelector);
var joinedItems = [];
for (var i = 0; i < outerGroups.length; i++) {
var outerGrp = outerGroups[i];
for (var ii = 0; ii < innerGroups.length; ii++) {
var innerGrp = innerGroups[ii];
if (!kc(outerGrp.key, innerGrp.key)) {
continue;
}
for (var iii = 0; iii < outerGrp.values.length; iii++) {
joinedItems.push(rc(outerGrp.values[iii], fromArray(innerGrp.values)));
}
}
}
return fromArray(joinedItems);
};
/** @inheritdoc */
Sequence.prototype.intersect = function (second, equalityComparer) {
var ec = toEqualityComparerSafe(equalityComparer);
second = asEnumerable(second).distinct(ec)
.toArray();
var newItems = [];
while (this.moveNext()) {
var curItem = this.current;
for (var i = 0; i < second.length; i++) {
var secondItem = second[i];
if (ec(curItem, secondItem)) {
newItems.push(curItem);
break;
}
}
}
return fromArray(newItems);
};
/** @inheritdoc */
Sequence.prototype.join = function (inner, outerKeySelector, innerKeySelector, resultSelector, keyEqualityComparer) {
inner = asEnumerable(inner);
var rc = asFunc(resultSelector);
var kc = toEqualityComparerSafe(keyEqualityComparer);
var createGroupsForSequence = function (seq, keySelector) {
return seq.groupBy(keySelector)
.select(function (grouping) {
return {
key: grouping.key,
values: grouping.toArray()
};
})
.toArray();
};
var outerGroups = createGroupsForSequence(this, outerKeySelector);
var innerGroups = createGroupsForSequence(inner, innerKeySelector);
var joinedItems = [];
for (var i = 0; i < outerGroups.length; i++) {
var outerGrp = outerGroups[i];
for (var ii = 0; ii < innerGroups.length; ii++) {
var innerGrp = innerGroups[ii];
if (!kc(outerGrp.key, innerGrp.key)) {
continue;
}
for (var iii = 0; iii < outerGrp.values.length; iii++) {
for (var iv = 0; iv < innerGrp.values.length; iv++) {
joinedItems.push(rc(outerGrp.values[iii], innerGrp.values[iv]));
}
}
}
}
return fromArray(joinedItems);
};
/** @inheritdoc */
Sequence.prototype.last = function (predicate) {
predicate = toPredicateSafe(predicate);
var index = -1;
var lastItem;
var found = false;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (predicate(ctx.item, ctx.index, ctx)) {
lastItem = ctx.item;
found = true;
}
if (ctx.cancel) {
break;
}
}
if (!found) {
throw "Sequence contains NO element!";
}
return lastItem;
};
/** @inheritdoc */
Sequence.prototype.lastOrDefault = function (predicateOrDefaultValue, defaultValue) {
var odObj = createObjectForOrDefaultMethod(arguments);
var index = -1;
var lastItem = odObj.defaultValue;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (odObj.predicate(ctx.item, ctx.index, ctx)) {
lastItem = ctx.item;
}
if (ctx.cancel) {
break;
}
}
return lastItem;
};
/** @inheritdoc */
Sequence.prototype.max = function (defaultValue) {
return this.aggregate(function (result, x) {
if (x > result) {
result = x;
}
return result;
}, defaultValue);
};
/** @inheritdoc */
Sequence.prototype.min = function (defaultValue) {
return this.aggregate(function (result, x) {
if (x < result) {
result = x;
}
return result;
}, defaultValue);
};
/** @inheritdoc */
Sequence.prototype.ofType = function (type) {
type = type.replace(exports.REGEX_TRIM, '');
var checkType = function (x) {
return typeof x === type;
};
switch (type) {
case 'bool':
type = 'boolean';
break;
case 'float':
case 'int':
case 'integer':
type = 'number';
break;
case 'str':
type = 'string';
break;
case 'enumerable':
case 'seq':
case 'sequence':
checkType = function (x) {
return isEnumerable(x);
};
break;
}
return this.where(checkType);
};
/** @inheritdoc */
Sequence.prototype.order = function (comparer) {
return this.orderBy('x => x', comparer);
};
/** @inheritdoc */
Sequence.prototype.orderBy = function (selector, comparer) {
return new OrderedSequence(this, selector, comparer);
};
/** @inheritdoc */
Sequence.prototype.orderByDescending = function (selector, comparer) {
var c = toComparerSafe(comparer);
return this.orderBy(selector, function (x, y) {
return c(y, x);
});
};
/** @inheritdoc */
Sequence.prototype.orderDescending = function (comparer) {
return this.orderByDescending('x => x', comparer);
};
/** @inheritdoc */
Sequence.prototype.pushToArray = function (arr) {
while (this.moveNext()) {
arr.push(this.current);
}
return this;
};
/** @inheritdoc */
Sequence.prototype.reverse = function () {
var reverseItems = [];
while (this.moveNext()) {
reverseItems.unshift(this.current);
}
return fromArray(reverseItems);
};
/** @inheritdoc */
Sequence.prototype.select = function (selector) {
this._selector = asFunc(selector);
return this;
};
/**
* Projects an item to another type based on the inner selector.
*
* @param {T} x The input value.
*
* @return any The output value.
*/
Sequence.prototype.selectInner = function (item) {
var s = this._selector;
if (TypeUtils.isNullOrUndefined(s)) {
s = function (x) { return x; };
}
return s(item);
};
/** @inheritdoc */
Sequence.prototype.selectMany = function (selector) {
selector = asFunc(selector);
var flattenItems = [];
var index = -1;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
var items = asEnumerable(selector(ctx.item, ctx.index, ctx));
while (items.moveNext()) {
flattenItems.push(items.current);
}
if (ctx.cancel) {
break;
}
}
return fromArray(flattenItems);
};
/** @inheritdoc */
Sequence.prototype.sequenceEqual = function (other, equalityComparer) {
var o = asEnumerable(other);
var ec = toEqualityComparerSafe(equalityComparer);
while (this.moveNext()) {
var x = this.current;
if (!o.moveNext()) {
return false;
}
var y = o.current;
if (!ec(x, y)) {
return false;
}
}
if (o.moveNext()) {
return false;
}
return true;
};
/** @inheritdoc */
Sequence.prototype.single = function (predicate) {
predicate = toPredicateSafe(predicate);
var index = -1;
var item;
var found = false;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (predicate(ctx.item, ctx.index, ctx)) {
if (found) {
throw "Sequence contains more that one matching element!";
}
item = this.current;
found = true;
}
if (ctx.cancel) {
break;
}
}
if (!found) {
throw "Sequence contains NO element!";
}
return item;
};
/** @inheritdoc */
Sequence.prototype.singleOrDefault = function (predicateOrDefaultValue, defaultValue) {
var odObj = createObjectForOrDefaultMethod(arguments);
var item = odObj.defaultValue;
var index = -1;
var found = false;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (odObj.predicate(ctx.item, ctx.index, ctx)) {
if (found) {
throw "Sequence contains more that one matching element!";
}
item = this.current;
found = true;
}
if (ctx.cancel) {
break;
}
}
return item;
};
/** @inheritdoc */
Sequence.prototype.skip = function (cnt) {
return this.skipWhile(function () {
if (cnt > 0) {
--cnt;
return true;
}
return false;
});
};
/** @inheritdoc */
Sequence.prototype.skipLast = function () {
var hasRemainingItems;
var isFirst = true;
var item;
var newItemList = [];
do {
hasRemainingItems = this.moveNext();
if (!hasRemainingItems) {
continue;
}
if (!isFirst) {
newItemList.push(item);
}
else {
isFirst = false;
}
item = this.current;
} while (hasRemainingItems);
return fromArray(newItemList);
};
/** @inheritdoc */
Sequence.prototype.skipWhile = function (predicate) {
predicate = asFunc(predicate);
var newItems = [];
var index = -1;
var flag = false;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (!flag && !predicate(ctx.item, ctx.index, ctx)) {
flag = true;
}
if (flag) {
newItems.push(ctx.item);
}
if (ctx.cancel) {
break;
}
}
return fromArray(newItems);
};
/** @inheritdoc */
Sequence.prototype.sum = function (defaultValue) {
return this.aggregate(function (result, x) {
return result + x;
}, defaultValue);
};
/** @inheritdoc */
Sequence.prototype.take = function (cnt) {
return this.takeWhile(function () {
if (cnt > 0) {
--cnt;
return true;
}
return false;
});
};
/** @inheritdoc */
Sequence.prototype.takeWhile = function (predicate) {
predicate = asFunc(predicate);
var newItems = [];
var index = -1;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (!predicate(ctx.item, ctx.index, ctx)) {
break;
}
newItems.push(ctx.item);
if (ctx.cancel) {
break;
}
}
return fromArray(newItems);
};
/** @inheritdoc */
Sequence.prototype.toArray = function () {
var arr = [];
while (this.moveNext()) {
arr.push(this.current);
}
return arr;
};
/** @inheritdoc */
Sequence.prototype.toLookup = function (keySelector, keyEqualityComparer) {
var lu = {};
this.groupBy(keySelector, keyEqualityComparer)
.each(function (grouping) {
lu[grouping.key] = grouping;
});
return lu;
};
/** @inheritdoc */
Sequence.prototype.toObject = function (keySelector) {
if (arguments.length < 1) {
keySelector = function (x, index, key) {
return key;
};
}
var ks = asFunc(keySelector);
var obj = {};
this.each(function (x, index, ctx) {
var key = ks(x, index, ctx.key);
obj[key] = x;
});
return obj;
};
/** @inheritdoc */
Sequence.prototype.toObservable = function (keySelector) {
if (arguments.length < 1) {
keySelector = function (x, index, key) {
return key;
};
}
var ks = asFunc(keySelector);
var ob = new observable_1.Observable();
this.each(function (x, index, ctx) {
var key = ks(x, index, ctx.key);
ob.set(key, x);
});
return ob;
};
/** @inheritdoc */
Sequence.prototype.toObservableArray = function () {
return new observable_array_1.ObservableArray(this.toArray());
};
/** @inheritdoc */
Sequence.prototype.toVirtualArray = function () {
var arr = this.toArray();
var va = new virtual_array_1.VirtualArray(arr.length);
for (var i = 0; i < va.length; i++) {
va.setItem(i, arr[i]);
}
return va;
};
/** @inheritdoc */
Sequence.prototype.union = function (second, equalityComparer) {
return this.concat(second)
.distinct(equalityComparer);
};
/** @inheritdoc */
Sequence.prototype.where = function (predicate) {
predicate = asFunc(predicate);
var filteredItems = [];
var index = -1;
while (this.moveNext()) {
var ctx = new EnumerableItemContext(this, ++index);
if (predicate(ctx.item, ctx.index, ctx)) {
filteredItems.push(ctx.item);
}
if (ctx.cancel) {
break;
}
}
return fromArray(filteredItems);
};
/** @inheritdoc */
Sequence.prototype.zip = function (second, selector) {
second = asEnumerable(second);
selector = asFunc(selector);
var zippedItems = [];
var index = -1;
while (this.moveNext() && second.moveNext()) {
++index;
var ctx1 = new EnumerableItemContext(this, index);
var ctx2 = new EnumerableItemContext(second, index);
var zipped = selector(ctx1.item, ctx2.item, index, ctx1, ctx2);
zippedItems.push(zipped);
if (ctx1.cancel || ctx2.cancel) {
break;
}
}
return fromArray(zippedItems);
};
return Sequence;
}());
exports.Sequence = Sequence;
var ArrayEnumerable = (function (_super) {
__extends(ArrayEnumerable, _super);
function ArrayEnumerable(arr, getter) {
_super.call(this);
this._arr = arr;
this._getter = getter;
this.reset();
}
ArrayEnumerable.prototype.getCurrent = function () {
return this._getter(this._index);
};
Object.defineProperty(ArrayEnumerable.prototype, "isValid", {
get: function () {
return (this._index + 1) < this._arr.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ArrayEnumerable.prototype, "itemKey", {
get: function () {
return this._index;
},
enumerable: true,
configurable: true
});
ArrayEnumerable.prototype.moveNext = function () {
if (this.isValid) {
++this._index;
return true;
}
return false;
};
ArrayEnumerable.prototype.reset = function () {
this._index = -1;
};
return ArrayEnumerable;
}(Sequence));
var EnumerableItemContext = (function () {
function EnumerableItemContext(seq, index) {
this.cancel = false;
this._seq = seq;
this._index = index;
}
Object.defineProperty(EnumerableItemContext.prototype, "index", {
get: function () {
return this._index;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnumerableItemContext.prototype, "item", {
get: function () {
return this._seq.current;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnumerableItemContext.prototype, "key", {
get: function () {
return this._seq.itemKey;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnumerableItemContext.prototype, "sequence", {
get: function () {
return this._seq;
},
enumerable: true,
configurable: true
});
return EnumerableItemContext;
}());
/**
* A grouping.
*/
var Grouping = (function (_super) {
__extends(Grouping, _super);
/**
* Initializes a new instance of that class.
*
* @param {K} key The key.
* @param {IEnumerable} seq The items of the grouping.
*/
function Grouping(key, seq) {
_super.call(this);
this._key = key;
this._seq = seq;
}
/** @inheritdoc */
Grouping.prototype.getCurrent = function () {
return this._seq.current;
};
Object.defineProperty(Grouping.prototype, "isValid", {
/** @inheritdoc */
get: function () {
return this._seq.isValid;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Grouping.prototype, "key", {
/** @inheritdoc */
get: function () {
return this._key;
},
enumerable: true,
configurable: true
});
/** @inheritdoc */
Grouping.prototype.moveNext = function () {
return this._seq.moveNext();
};
/** @inheritdoc */
Grouping.prototype.reset = function () {
return this._seq.reset();
};
return Grouping;
}(Sequence));
exports.Grouping = Grouping;
var ObjectEnumerable = (function (_super) {
__extends(ObjectEnumerable, _super);
function ObjectEnumerable(obj) {
_super.call(this);
this._properties = [];
for (var p in obj) {
this._properties.push(p);
}
this.reset();
}
ObjectEnumerable.prototype.getCurrent = function () {
return this._obj[this.itemKey];
};
Object.defineProperty(ObjectEnumerable.prototype, "isValid", {
get: function () {
return (this._index + 1) < this._properties.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectEnumerable.prototype, "itemKey", {
get: function () {
return this._properties[this._index];
},
enumerable: true,
configurable: true
});
ObjectEnumerable.prototype.moveNext = function () {
if (this.isValid) {
++this._index;
return true;
}
return false;
};
ObjectEnumerable.prototype.reset = function () {
this._index = -1;
};
return ObjectEnumerable;
}(Sequence));
/**
* An ordered sequence.
*/
var OrderedSequence = (function (_super) {
__extends(OrderedSequence, _super);
/**
* Initializes a new instance of that class.
*
* @param {IEnumerable} seq The source sequence.
* @param {Function} selector The selector for the sort values.
* @param {Function} comparer The comparer to use.
*/
function OrderedSequence(seq, selector, comparer) {
_super.call(this);
var me = this;
this._orderComparer = toComparerSafe(comparer);
if (true === selector) {
selector = function (x) { return x; };
}
this._orderSelector = asFunc(selector);
this._originalItems = seq.toArray();
this._items = fromArray(this._originalItems.map(function (x) {
return {
sortBy: me.selector(x),
value: x
};
}).sort(function (x, y) {
return me.comparer(x.sortBy, y.sortBy);
}).map(function (x) {
return x.value;
}));
}
Object.defineProperty(OrderedSequence.prototype, "comparer", {
/**
* Gets the comparer.
*/
get: function () {
return this._orderComparer;
},
enumerable: true,
configurable: true
});
/** @inheritdoc */
OrderedSequence.prototype.getCurrent = function () {
return this._items.current;
};
/** @inheritdoc */
OrderedSequence.prototype.moveNext = function () {
return this._items
.moveNext();
};
/** @inheritdoc */
OrderedSequence.prototype.reset = function () {
return this._items.reset();
};
Object.defineProperty(OrderedSequence.prototype, "selector", {
/**
* Gets the selector.
*/
get: function () {
return this._orderSelector;
},
enumerable: true,
configurable: true
});
/** @inheritdoc */
OrderedSequence.prototype.then = function (comparer) {
return this.thenBy('x => x', comparer);
};
/** @inheritdoc */
OrderedSequence.prototype.thenBy = function (selector, comparer) {
var c = toComparerSafe(comparer);
if (true === selector) {
selector = function (x) { return x; };
}
selector = asFunc(selector);
var thisSelector = this._orderSelector;
var thisComparer = this._orderComparer;
return fromArray(this._originalItems)
.orderBy(function (x) {
return {
level_0: thisSelector(x),
level_1: selector(x),
};
}, function (x, y) {
var comp0 = thisComparer(x.level_0, y.level_0);
if (0 != comp0) {
return comp0;
}
var comp1 = c(x.level_1, y.level_1);
if (0 != comp1) {
return comp1;
}
return 0;
});
};
/** @inheritdoc */
OrderedSequence.prototype.thenByDescending = function (selector, comparer) {
var c = toComparerSafe(comparer);
return this.thenBy(selector, function (x, y) {
return comparer(y, x);
});
};
/** @inheritdoc */
OrderedSequence.prototype.thenDescending = function (comparer) {
return this.thenByDescending('x => x', comparer);
};
return OrderedSequence;
}(Sequence));
exports.OrderedSequence = OrderedSequence;
/**
* Returns a value as sequence.
*
* @param any v The input value.
* @param {Boolean} [throwException] Throws an exception if input value is no valid value.
*
* @throws Invalid value.
*
* @return any The value as sequence or (false) if input value is no valid object.
*/
function asEnumerable(v, throwException) {
if (throwException === void 0) { throwException = true; }
if (isEnumerable(v)) {
return v;
}
if ((v instanceof Array) ||
(v instanceof observable_array_1.ObservableArray) ||
(v instanceof virtual_array_1.VirtualArray) ||
(typeof v === 'string') ||
!v) {
return fromArray(v);
}
if (typeof v === 'object') {
return fromObject(v);
}
// at this point we have no valid value to use as sequence
if (throwException) {
throw "'" + v + "' is no valid value to use as sequence!";
}
return false;
}
exports.asEnumerable = asEnumerable;
/**
* Returns a value as function.
*
* @param any v The value to convert. Can be a function or a string that is handled as lambda expression.
* @param {Boolean} [throwException] Throw an exception if value is no valid function or not.
*
* @throws Value is no valid function / lambda expression.
*
* @return {Function} Value as function or (false) if value is invalid.
*/
function asFunc(v, throwException) {
if (throwException === void 0) { throwException = true; }
if (typeof v === "function") {
return v;
}
if (!v) {
return v;
}
// now handle as lambda...
var lambda = "" + v;
var matches = lambda.match(/^(\s*)([\(]?)([^\)]*)([\)]?)(\s*)(=>)/m);
if (matches) {
if ((("" === matches[2]) && ("" !== matches[4])) ||
(("" !== matches[2]) && ("" === matches[4]))) {
if (throwException) {
throw "Syntax error in '" + lambda + "' expression!";
}
return null;
}
var lambdaBody = lambda.substr(matches[0].length)
.replace(/^[\s|{|}]+|[\s|{|}]+$/g, ''); // trim
if ("" !== lambdaBody) {
if (';' !== lambdaBody.substr(-1)) {
lambdaBody = 'return ' + lambdaBody + ';';
}
}
var func;
eval('func = function(' + matches[3] + ') { ' + lambdaBody + ' };');
return func;
}
if (throwException) {
throw "'" + v + "' is NO valid lambda expression!";
}
return false;
}
exports.asFunc = asFunc;
/**
* Creates a new sequence from a list of values.
*
* @param any ...items One or more item to add.
*
* @return {IEnumerable} The new sequence.
*/
function create() {
var items = [];
for (var _i = 0; _i < arguments.length; _i++) {
items[_i - 0] = arguments[_i];
}
return fromArray(items);
}
exports.create = create;
function createObjectForOrDefaultMethod(args) {
var odObj = {
predicate: function () { return true; },
};
if (args.length > 0) {
if (args.length < 2) {
var func = asFunc(args[0], false);
if (typeof func !== "function") {
odObj.defaultValue = args[0];
}
else {
odObj.predicate = func;
}
}
else {
odObj.predicate = asFunc(args[0]);
odObj.defaultValue = args[1];
}
}
return odObj;
}
/**
* Short hand version for 'each' method of a sequence.
*
* @param items any The sequence of items to iterate.
* @param action any The action to invoke for each item.
*
* @throws At least one argument is invalid.
*
* @return any The result of the last invocation.
*/
function each(items, action) {
return asEnumerable(items).each(action);
}
exports.each = each;
/**
* Creates a new sequence from an array.
*
* @param {Array} arr The array.
*
* @return {IEnumerable} The new sequence.
*/
function fromArray(arr) {
if (arguments.length < 1) {
arr = [];
}
var getter;
if ((arr instanceof observable_array_1.ObservableArray) ||
(arr instanceof virtual_array_1.VirtualArray)) {
getter = function (i) { return arr.getItem(i); };
}
else {
getter = function (i) { return arr[i]; };
}
return new ArrayEnumerable(arr, getter);
}
exports.fromArray = fromArray;
/**
* Creates a new sequence from an object.
*
* @param {Object} obj The object.
*
* @return {Sequence} The new sequence.
*/
function fromObject(obj) {
if (arguments.length < 1) {
obj = {};
}
return new ObjectEnumerable(obj);
}
exports.fromObject = fromObject;
/**
* Checks if a value is a sequence.
*
* @param any v The value to check.
*
* @return {Boolean} Is sequence or not.
*/
function isEnumerable(v) {
return v instanceof Sequence;
}
exports.isEnumerable = isEnumerable;
/**
* Creates a sequence with a range of items.
*
* @param any start The start value.
* @param {Number} cnt The number of items to return.
* @param any [incrementor] The custom function (or value) that increments the current value.
*
* @return {Object} The new sequence.
*/
function range(start, cnt, incrementor) {
if (arguments.length < 3) {
incrementor = function (x) {
return x + 1;
};
}
else {
var funcOrValue = asFunc(incrementor, false);
if (false === funcOrValue) {
var incrementBy = incrementor;
incrementor = function (x) {
return x + incrementBy;
};
}
else {
incrementor = funcOrValue;
}
}
var numbers = [];
var remainingCnt = cnt;
var val = start;
while (remainingCnt > 0) {
numbers.push(val);
val = incrementor(val, {
remainingCount: remainingCnt,
startValue: start,
totalCount: cnt
});
--remainingCnt;
}
return fromArray(numbers);
}
/**
* Creates a sequence with a number of specific values.
*
* @param any v The value.
* @param {Number} cnt The number of items to return.
*
* @return {Object} The new sequence.
*/
function repeat(v, cnt) {
var items = [];
while (cnt > 0) {
items.push(v);
--cnt;
}
return fromArray(items);
}
/**
* Short hand version for 'order(By)' methods of a sequence.
*
* @param items any The sequence of items to iterate.
* @param [comparer] any The custom comparer to use.
* @param [selector] any The custom key selector to use.
*
* @throws At least one argument is invalid.
*
* @return {IOrderedEnumerable} The sequences with the sorted items.
*/
function sort(items, comparer, selector) {
return asEnumerable(items).orderBy(selector, comparer);
}
exports.sort = sort;
/**
* Short hand version for 'order(By)Descending' methods of a sequence.
*
* @param items any The sequence of items to iterate.
* @param [comparer] any The custom comparer to use.
* @param [selector] any The custom key selector to use.
*
* @throws At least one argument is invalid.
*
* @return {IOrderedEnumerable} The sequences with the sorted items.
*/
function sortDesc(items, comparer, selector) {
return asEnumerable(items).orderByDescending(selector, comparer);
}
exports.sortDesc = sortDesc;
/**
* Returns a value as comparer.
*
* @param any predicate The input value.
*
* @throws Input value is no valid function / lambda expression.
*
* @return {Function} Input value as comparer.
*/
function toComparerSafe(comparer) {
comparer = asFunc(comparer);
if (TypeUtils.isNullOrUndefined(comparer)) {
return function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
};
}
return comparer;
}
exports.toComparerSafe = toComparerSafe;
;
/**
* Returns a value as equality comparer.
*
* @param any equalityComparer The input value.
*
* @throws Input value is no valid function / lambda expression.
*
* @return {Function} Input value as equality comparer.
*/
function toEqualityComparerSafe(equalityComparer) {
if (true === equalityComparer) {
return function (x, y) {
return x === y;
};
}
equalityComparer = asFunc(equalityComparer);
if (TypeUtils.isNullOrUndefined(equalityComparer)) {
return function (x, y) {
return x == y;
};
}
return equalityComparer;
}
exports.toEqualityComparerSafe = toEqualityComparerSafe;
/**
* Returns a value as predicate.
*
* @param any predicate The input value.
*
* @throws Input value is no valid function / lambda expression.
*
* @return {Function} Input value as predicate.
*/
function toPredicateSafe(predicate) {
if (TypeUtils.isNullOrUndefined(predicate)) {
predicate = function () { return true; };
}
return asFunc(predicate);
}
exports.toPredicateSafe = toPredicateSafe;
//# sourceMappingURL=index.js.map