nowjs-core
Version:
NowCanDo Javascript Core [nowjs-core] is a library written by TypeScript code maintains under Apache 2.0 licence
936 lines (935 loc) • 30.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = require("../exceptions/index");
const Collectors_1 = require("../collections/Collectors");
const List_1 = require("../collections/List");
const Collection_1 = require("../collections/Collection");
const ObjectUtils_1 = require("../utils/ObjectUtils");
class Enumerable {
constructor(enumerable, options) {
this.enumerable = enumerable;
this.options = options;
if (!enumerable)
enumerable = [];
this.options = options || {};
}
collect(factory) {
factory = factory || Collectors_1.Collectors.toIEnumerable();
return factory(this.enumerable);
}
static from(enumerable) {
return new Enumerable(enumerable);
}
static repeat(result, count) {
const itr = {
[Symbol.iterator]: () => {
let counter = 0;
return {
next: () => {
if (counter < count) {
counter++;
return {
value: typeof result === 'function'
?
result.apply(result)
: result,
done: false,
};
}
else {
return { done: true };
}
},
};
},
};
return new Enumerable(itr);
}
static range(start, count, step = 1) {
const itr = {
[Symbol.iterator]: () => {
let curr = start - 1;
let counter = 0;
return {
next: () => {
if (counter >= count) {
return { done: true };
}
else {
counter++;
curr += step;
return { value: curr, done: false };
}
},
};
},
};
return new Enumerable(itr);
}
static comparator(a, b) {
if (a === b) {
return 0;
}
else if (a > b) {
return 1;
}
else {
return -1;
}
}
static equalityComparator(a, b) {
return a === b ? 0 : -1;
}
static selector(t) {
return t;
}
aggregate(action, seed) {
const arr1 = this.toArray();
if (seed == null)
seed = arr1.shift();
for (let i = 0; i < arr1.length; i++) {
seed = action(seed, arr1[i], i, this);
}
return seed;
}
all(predicate) {
for (const xx of this.enumerable) {
if (predicate(xx) === false) {
return false;
}
}
return true;
}
any(predicate) {
for (const xx of this) {
if (predicate(xx) === true) {
return true;
}
}
return false;
}
first(predicate, defValue) {
defValue = defValue ? defValue : null;
for (const xx of this.enumerable) {
if (predicate) {
if (predicate(xx) === true) {
return xx;
}
}
else {
return xx;
}
}
return defValue;
}
last(predicate, defValue) {
defValue = defValue ? defValue : null;
for (const xx of this.enumerable) {
if (predicate) {
if (predicate(xx) === true) {
defValue = xx;
}
}
else {
defValue = xx;
}
}
return defValue;
}
single(predicate, defValue) {
defValue = defValue ? defValue : null;
for (const xx of this.enumerable) {
if (predicate) {
if (predicate(xx) === true) {
return xx;
}
}
else {
return xx;
}
}
return defValue;
}
contains(item) {
for (const x of this) {
if (x === item) {
return true;
}
}
return false;
}
isEmpty() {
if (this.enumerable && this.enumerable[Symbol.iterator]) {
return this.enumerable[Symbol.iterator]().next().done;
}
return true;
}
skip(count) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
const enb = thisme.enumerable[Symbol.iterator]();
for (let i = 0; i < count; i++) {
enb.next();
}
return {
next: () => {
return enb.next();
},
};
},
};
return new Enumerable(itr);
}
skipWhile(predicate) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
let xx;
const enb = thisme.enumerable[Symbol.iterator]();
do {
xx = enb.next();
if (xx && predicate(xx.value) === true) {
return {
next: () => {
if (xx) {
const yy = xx;
xx = null;
return yy;
}
return enb.next();
},
};
}
} while (xx.done === false);
},
};
return new Enumerable(itr);
}
take(count) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
let i = 0;
const enb = thisme.enumerable[Symbol.iterator]();
return {
next: () => {
const x = enb.next();
if (i === count) {
x.done = true;
}
i++;
return x;
},
};
},
};
return new Enumerable(itr);
}
takeWhile(predicate) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
let xx;
const enb = thisme.enumerable[Symbol.iterator]();
return {
next: () => {
xx = enb.next();
if (xx && predicate(xx.value) === true) {
xx.done = true;
}
return xx;
},
};
},
};
return new Enumerable(itr);
}
distinct() {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
const enb = thisme.enumerable[Symbol.iterator]();
const traversed = new Set();
return {
next: () => {
while (true) {
const item = enb.next();
if (item.done === true) {
return item;
}
if (!traversed.has(item.value)) {
traversed.add(item.value);
return item;
}
}
},
};
},
};
return new Enumerable(itr);
}
reverse() {
const revIt = this.toArray().reverse();
return new Enumerable(revIt);
}
shuffles(count) {
const thisme = this;
const arr = this.toArray();
const res = [];
const mrands = Enumerable.repeat(() => {
return Math.floor(Math.random() * arr.length);
}, count);
for (const item of mrands) {
res.push(arr[item]);
}
return new Enumerable(res);
}
asEnumerable() {
return new Enumerable(this.enumerable);
}
select(selector) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
const enb = thisme.enumerable[Symbol.iterator]();
return {
next: () => {
const nx = enb.next();
if (nx.done === false) {
nx.value = selector ? selector(nx.value) : nx.value;
}
return nx;
},
};
},
};
return new Enumerable(itr);
}
selectMany(selector, collectionSelector) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
const itr1 = thisme.enumerable[Symbol.iterator]();
let citer = null;
const itm = () => {
if (!citer) {
const pnv = itr1.next();
if (pnv && pnv.done === false) {
if (selector) {
const childv = selector(pnv.value);
if (childv && childv[Symbol.iterator]) {
citer = childv[Symbol.iterator]();
}
}
}
else {
return pnv;
}
}
if (citer) {
const nv = citer.next();
if (nv.done === false) {
if (collectionSelector) {
return { value: collectionSelector(nv.value), done: nv.done };
}
else {
return nv;
}
}
else {
citer = null;
return itm();
}
}
};
return {
next: () => {
return itm();
},
};
},
};
return new Enumerable(itr);
}
indexOf(item) {
let indx = -1;
for (const xx of this) {
indx++;
if (xx === item) {
return indx;
}
}
return -1;
}
lastIndexOf(item) {
let indx = -1;
let findex = -1;
for (const xx of this) {
indx++;
if (xx === item) {
findex = indx;
}
}
return findex;
}
join(inner, outerSelector, innerSelector, resultSelector) {
const itr = {
[Symbol.iterator]: () => {
const enbOuter = this[Symbol.iterator]();
let enbg;
const getGroup = (groups, key) => {
if (!enbg) {
enbg = groups[Symbol.iterator]();
}
while (true) {
const ixg = enbg.next();
if (ixg.done === false && ixg.value && ixg.value.key === key) {
return ixg.value;
}
if (ixg.done === true) {
return null;
}
}
};
const ig = new Enumerable(inner).groupBy(innerSelector);
let oit;
let xOuter;
return {
next: () => {
if (oit) {
const g = oit.next();
if (g.done === false) {
const xx = {
done: false,
value: resultSelector(xOuter.value, g.value),
};
return xx;
}
else {
oit = null;
}
}
xOuter = enbOuter.next();
if (xOuter && xOuter.done === false) {
const og = getGroup(ig, outerSelector(xOuter.value));
if (og) {
oit = og.values[Symbol.iterator]();
if (oit) {
const g = oit.next();
if (g.done === false) {
const xx = {
done: false,
value: resultSelector(xOuter.value, g.value),
};
return xx;
}
else {
oit = null;
}
}
}
}
return { done: true };
},
};
},
};
return new Enumerable(itr);
}
where(predicate) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
const enb = thisme[Symbol.iterator]();
const getNext = () => {
let xx;
do {
xx = enb.next();
if (xx && xx.done === false && predicate(xx.value) === true) {
break;
}
} while (xx.done === false);
return xx;
};
return {
next: () => {
if (predicate) {
return getNext();
}
else {
return enb.next();
}
},
};
},
};
return new Enumerable(itr);
}
except(predicate) {
const thisme = this;
const itr = {
[Symbol.iterator]: () => {
let xx;
const enb = thisme.enumerable[Symbol.iterator]();
return {
next: () => {
xx = enb.next();
if (xx && predicate(xx.value) === true) {
do {
xx = enb.next();
if (xx && predicate(xx.value) === false) {
break;
}
} while (xx.done === false);
}
return xx;
},
};
},
};
return new Enumerable(itr);
}
orderBy(selector, comparator) {
comparator = comparator || Enumerable.comparator;
selector = selector || ((xx) => xx);
const cmp = (a, b) => {
return comparator(selector(a), selector(b));
};
const enb = this[Symbol.iterator]();
let arr = this.toArray();
arr = arr.sort(cmp);
return new OrderedEnumerable(arr);
}
orderByDesc(selector, comparator) {
comparator = comparator || Enumerable.comparator;
return this.orderBy(selector, (a, b) => {
return -comparator(a, b);
});
}
internalGroupBy(source, keySelector, parentKey) {
const groups = new Map();
for (const item of source) {
if (item.key && item.values) {
const gitems = this.internalGroupBy(item.values, keySelector, item.key);
for (const gitem of gitems) {
const s = groups.get(gitem.key);
if (s) {
const lis = [];
for (const li of gitem.values) {
lis.push(li);
}
for (const si of s) {
lis.push(si);
}
gitem.values = new Enumerable(lis);
}
else {
groups.set(gitem.key, gitem.values);
}
}
}
else {
const key = parentKey ? keySelector({ key: item }) : keySelector(item);
let flist = null;
if (typeof key === 'object') {
for (const [k, v] of groups.entries()) {
if (ObjectUtils_1.deepEqual(key, k)) {
flist = v;
break;
}
}
}
else {
flist = groups.get(key);
}
if (flist) {
flist.push(item);
}
else {
const lst = [];
lst.push(item);
groups.set(key, lst);
}
}
}
const list = [];
groups.forEach((v, k) => {
list.push({ key: k, values: new Enumerable(v) });
});
return new Enumerable(list);
}
groupBy(keySelector) {
return this.internalGroupBy(this, keySelector);
}
count(predicate) {
let i = -1;
for (const xx of this) {
if (predicate) {
if (predicate(xx)) {
i++;
}
}
else {
i++;
}
}
return i + 1;
}
average(selector, predicate) {
let res = 0;
let count = 0;
for (const x of this.enumerable) {
const xx = selector ? selector(x) : x;
if (selector && predicate) {
if (predicate(xx) === true) {
res += xx;
count++;
}
}
else {
res += xx;
count++;
}
}
return res / count;
}
max(selector, predicate) {
let res = selector ? selector(this.first()) : this.first();
for (const x of this) {
const xx = selector ? selector(x) : x;
if (selector && predicate) {
if (predicate(xx) === true) {
if (Enumerable.comparator(xx, res) === 1) {
res = xx;
}
}
}
else {
if (Enumerable.comparator(xx, res) === 1) {
res = xx;
}
}
}
return res;
}
min(selector, predicate) {
let res;
for (const x of this) {
const xx = selector ? selector(x) : x;
if (selector && predicate) {
if (predicate(xx) === true) {
if (Enumerable.comparator(xx, res) === -1) {
res = xx;
}
}
}
else {
if (Enumerable.comparator(xx, res) === -1) {
res = xx;
}
}
}
return res;
}
sum(selector, predicate) {
let res = 0;
for (const x of this) {
const xx = selector ? selector(x) : x;
if (selector && predicate) {
if (predicate(xx) === true) {
res += xx;
}
}
else {
res += xx;
}
}
return res;
}
stdDev(selector, predicate) {
const source = this.where(predicate).select(selector);
const count = source.count();
const avg = source.average();
const sum = source.sum(d => (d - avg) * (d - avg));
const ret = Math.sqrt(sum / count);
return ret;
}
stdDevP(selector, predicate) {
const source = this.where(predicate).select(selector);
const count = source.count();
const avg = source.average();
const sum = source.sum(d => (d - avg) * (d - avg));
const ret = Math.sqrt(sum / (count - 1));
return ret;
}
variance(selector, predicate) {
const source = this.where(predicate).select(selector);
const count = source.count();
if (count === 0)
return 0;
const mean = source.average();
const squareDiffs = source.select(item => {
const d = item;
return (d - mean) * (d - mean);
});
const ret = squareDiffs.average();
return ret;
}
rootMeanSquare(selector, predicate) {
const source = this.where(predicate).select(selector);
const count = source.count();
const s = source.aggregate((x, d) => (x += Math.pow(d, 2)));
return Math.sqrt(s / count);
}
covariance(other, selector, predicate) {
const source = this.where(predicate).select(selector);
const target = other.where(predicate).select(selector);
const sourcecount = this.count(predicate);
const sourceAvg = source.average();
const targetAvg = target.average();
let ret = 0;
for (let i = 0; i < sourcecount; i++)
ret += (source.get(i) - sourceAvg) * (other.get(i) - targetAvg);
return ret / (sourcecount - 1);
}
pearson(other, selector, predicate) {
const source = this.where(predicate).select(selector);
const target = other.where(predicate).select(selector);
return source.covariance(target) / (source.stdDevP() * other.stdDevP());
}
varianceP(selector, predicate) {
const source = this.where(predicate).select(selector);
const count = source.count();
if (count === 0)
return 0;
const mean = source.average();
const squareDiffs = source.select(item => {
const d = item;
return (d - mean) * (d - mean);
});
const ret = squareDiffs.sum() / (count - 1);
return ret;
}
percentile(percentile, selector, predicate) {
return this.percentileInclusive(percentile, selector, predicate);
}
percentileInclusive(percentile, selector, predicate) {
const source = this.where(predicate)
.select(selector)
.orderBy(key => key);
const length = source.count();
const index = percentile * (length - 1);
const integerComponentOfIndex = Math.floor(index);
const decimalComponentOfIndex = index - integerComponentOfIndex;
const keyAtIndex = source.get(integerComponentOfIndex);
if (integerComponentOfIndex >= length - 1) {
return keyAtIndex;
}
const keyAtNextIndex = source.get(integerComponentOfIndex);
return keyAtIndex + (keyAtNextIndex - keyAtIndex) * decimalComponentOfIndex;
}
percentileExclusive(percentile, selector, predicate) {
const source = this.where(predicate)
.select(selector)
.orderBy(key => key);
const length = source.count();
const index = percentile * (length + 1) - 1;
const integerComponentOfIndex = Math.floor(index);
const decimalComponentOfIndex = index - integerComponentOfIndex;
const keyAtIndex = source.get(integerComponentOfIndex);
const keyAtNextIndex = source.get(integerComponentOfIndex);
return keyAtIndex + (keyAtNextIndex - keyAtIndex) * decimalComponentOfIndex;
}
percentRank(value, selector, predicate) {
selector = selector || ((xx) => xx);
const source = this.where(predicate).orderBy(selector);
const array = source.toArray();
let L = 0;
let S = 0;
const N = array.length;
for (let i = 0; i < array.length; i++) {
if (array[i] < value) {
L += 1;
}
else if (array[i] === value) {
S += 1;
}
}
const pct = (L + 0.5 * S) / N;
return pct;
}
mean(selector, predicate) {
selector = selector || ((xx) => xx);
return this.average(selector, predicate);
}
median(selector, predicate) {
selector = selector || ((xx) => xx);
const source = this.where(predicate).orderBy(selector);
const count = source.count();
const mindex = Math.floor(count / 2);
if (count % 2 === 0) {
return (((selector ? selector(source.get(mindex)) : source.get(mindex)) +
(selector ? selector(source.get(mindex - 1)) : source.get(mindex - 1))) /
2);
}
return selector ? selector(source.get(mindex)) : source.get(mindex);
}
mode(selector, predicate) {
selector = selector || ((xx) => xx);
const source = this.where(predicate).select(selector);
const array = source.toArray();
let hasDuplicate = false;
if (array.length < 2)
return Number.NaN;
let maxValue = Number.MIN_VALUE, maxCount = 0;
for (let i = 0; i < array.length; ++i) {
let count = 0;
if (!hasDuplicate && array.lastIndexOf(array[i]) !== i) {
hasDuplicate = true;
}
for (let j = 0; j < array.length; ++j) {
if (array[j] === array[i])
++count;
}
if (count > maxCount) {
maxCount = count;
maxValue = array[i];
}
}
if (!hasDuplicate)
return Number.NaN;
return maxValue === Number.MIN_VALUE ? Number.NaN : maxValue;
}
range(selector, predicate) {
selector = selector || ((xx) => xx);
const source = this.where(predicate).select(selector);
const ret = source.max() - source.min();
return ret;
}
get(index) {
const enb = this[Symbol.iterator]();
for (let i = 0; i <= index; i++) {
const next = enb.next();
if (i === index)
return next.value;
}
return null;
}
forEach(action) {
let i = 0;
for (const x of this) {
action(x, i++);
}
}
toArray() {
const aa = [];
for (const x of this) {
aa.push(x);
}
return aa;
}
toList() {
const xx = new List_1.List();
for (const x of this) {
xx.add(x);
}
return xx;
}
toCollection() {
const xx = new Collection_1.Collection();
for (const x of this) {
xx.add(x);
}
return xx;
}
intersect(source, equalityComparator) {
equalityComparator = equalityComparator || Enumerable.equalityComparator;
const wset = new Set();
for (const xx of source) {
if (this.contains(xx)) {
wset.add(xx);
}
}
return new Enumerable(wset);
}
subtract(source, equalityComparator) {
equalityComparator = equalityComparator || Enumerable.equalityComparator;
const wset = new Set();
const inter = this.intersect(source);
for (const xx of this) {
if (!inter.contains(xx)) {
wset.add(xx);
}
}
return new Enumerable(wset);
}
union(source, equalityComparator) {
equalityComparator = equalityComparator || Enumerable.equalityComparator;
const wset = new Set();
for (const xx of this) {
wset.add(xx);
}
for (const xx of source) {
if (!wset.has(xx)) {
wset.add(xx);
}
}
return new Enumerable(wset);
}
zip(second, selector) {
const thisme = this;
const enb1 = thisme.enumerable[Symbol.iterator]();
const enb2 = new Enumerable(second)[Symbol.iterator]();
const itr = {
[Symbol.iterator]: () => {
return {
next: () => {
const item1 = enb1.next();
const item2 = enb2.next();
if (item1.done === false && item2.done === false) {
return { value: selector(item1.value, item2.value), done: false };
}
else {
return { done: true };
}
},
};
},
};
return new Enumerable(itr);
}
[Symbol.iterator]() {
if (this.enumerable && this.enumerable[Symbol.iterator]) {
return this.enumerable[Symbol.iterator]();
}
throw new index_1.IllegalOperationException(-250, 'The object is not itrabe .');
}
}
exports.Enumerable = Enumerable;
class OrderedEnumerable extends Enumerable {
constructor(enumerable, options) {
super(enumerable, options);
}
thenBy(selector, comparator) {
comparator = comparator || Enumerable.comparator;
const cmp = (a, b) => {
return comparator(selector(a), selector(b));
};
return this.orderBy(Enumerable.selector, (a, b) => {
const res = cmp(a, b);
return res === 0 ? comparator(selector(a), selector(b)) : res;
});
}
thenByDesc(selector, comparator) {
comparator = comparator || Enumerable.comparator;
const cmp = (a, b) => {
return comparator(selector(a), selector(b));
};
return this.orderBy(Enumerable.selector, (a, b) => {
const res = cmp(a, b);
return res === 0 ? -comparator(selector(a), selector(b)) : res;
});
}
}
exports.OrderedEnumerable = OrderedEnumerable;