UNPKG

@beenotung/tslib

Version:
667 lines 17.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pushBackward = exports.pushForward = exports.getMaxArraySize = exports.flattenAll = exports.genCombination = exports.shuffledIndecies = exports.shuffledIndices = exports.shuffledBinArray = exports.shuffle = exports.mode = exports.countAll = exports.countElement = exports.median = exports.sumByField = exports.minByField = exports.maxByField = exports.minByFunc = exports.maxByFunc = exports.sumByFunc = exports.sum = exports.min = exports.max = exports.asyncCountArray = exports.countArray = exports.mapArray = exports.zipArray = exports.partitionArrayBy = exports.binArrayBy = exports.binArray = exports.push = exports.flatten = exports.toArray = exports.filterByKey = exports.repeat = exports.range = exports.removeByKey = exports.removeDupByKey = exports.insertNoDupWithKey = exports.insertNoDup = exports.removeDup = exports.nodup = exports.removeBy = exports.remove = exports.removeByIdx = exports.sort = exports.sortBy = exports.insertSortBy = exports.cloneArray = exports.defaultComparator = exports.insert_sorted = exports.insert = exports.array_contains = exports.fromFileList = exports.maybeLast = exports.last = exports.shiftUntilN = exports.shiftN = exports.popUntilN = exports.popN = exports.leftMost = exports.rightMost = exports.unique = exports.includes = exports.takeAll = exports.replaceArray = exports.clear = exports.clearArray = void 0; const compare_1 = require("./compare"); const lang_1 = require("./lang"); const map_1 = require("./map"); const maybe_1 = require("./maybe"); const random_1 = require("./random"); const string_1 = require("./string"); /** * inplace delete all element from the array * @return old elements * */ function clearArray(xs) { return xs.splice(0, xs.length); } exports.clearArray = clearArray; /** @deprecated renamed to clearArray */ exports.clear = clearArray; /** * inplace replace all element in the array * @return the old elements * */ function replaceArray(dest, src) { clearArray(dest); dest.push(...src); return dest; } exports.replaceArray = replaceArray; /**@remark side effect * inplace operation * @deprecated same as clear * */ function takeAll(xs) { const res = [].concat(xs); exports.clear(xs); return res; } exports.takeAll = takeAll; function includes(x, xs) { return xs.indexOf(x) !== -1; } exports.includes = includes; /** * only use `===` to compare * @warning slow * @return new array * */ function unique(xs) { return Array.from(new Set(xs)); } exports.unique = unique; function rightMost(n, xs) { return xs.slice(xs.length - n, xs.length); } exports.rightMost = rightMost; function leftMost(n, xs) { return xs.slice(0, n); } exports.leftMost = leftMost; /** inplace update */ function popN(n, xs) { lang_1.forI(_ => xs.pop(), n); } exports.popN = popN; /** inplace update */ function popUntilN(n, xs) { lang_1.forI(_ => xs.pop(), xs.length - n); } exports.popUntilN = popUntilN; /** inplace update */ function shiftN(n, xs) { lang_1.forI(_ => xs.shift(), n); } exports.shiftN = shiftN; /** inplace update */ function shiftUntilN(n, xs) { lang_1.forI(_ => xs.shift(), xs.length - n); } exports.shiftUntilN = shiftUntilN; function last(xs, skipCheck = false) { if (!skipCheck && xs.length === 0) { throw new TypeError('xs is not non-empty array'); } return xs[xs.length - 1]; } exports.last = last; function maybeLast(xs) { return maybe_1.Maybe.fromNullable(xs[xs.length - 1]); } exports.maybeLast = maybeLast; function fromFileList(files) { return lang_1.mapI(i => files.item(i), files.length); } exports.fromFileList = fromFileList; function array_contains(xs, x) { return xs.indexOf(x) !== -1; } exports.array_contains = array_contains; function insert(xs, index, x) { xs.splice(index, 0, x); } exports.insert = insert; /** * insert into Ascending sorted array * */ function insert_sorted(xs, comparator, x, order = 'ascending') { const target = order === 'ascending' ? compare_1.CompareResult.Larger : compare_1.CompareResult.Smaller; for (let i = 0; i < xs.length; i++) { if (comparator(xs[i], x) === target) { insert(xs, i, x); return; } } xs.push(x); } exports.insert_sorted = insert_sorted; exports.defaultComparator = (a, b) => { if (typeof a === 'string' && typeof b === 'string') { return string_1.compare_string(a, b); } return compare_1.compare(a, b); }; /** * * wrapper of slice, because it's confusing between slice and splice * * performance reference: https://jsperf.com/array-clone * */ function cloneArray(xs) { return xs.slice(); } exports.cloneArray = cloneArray; /** * @return new array (not deep cloning elements) * @deprecated use clone() and array.sort() explicitly is better * */ function insertSortBy(xs, comparator) { const res = new Array(xs.length); xs.forEach(x => insert_sorted(res, comparator, x)); return res; } exports.insertSortBy = insertSortBy; /**@deprecated*/ exports.sortBy = insertSortBy; /** * @return in-place sorted, original array * */ function sort(xs, comparator = exports.defaultComparator) { return xs.sort(comparator); } exports.sort = sort; /** * @remark inplace update * @return original array * */ function removeByIdx(xs, i) { xs.splice(i, 1); return xs; } exports.removeByIdx = removeByIdx; /** * @remark inplace update * @return original array * */ function remove(xs, x) { const idx = xs.indexOf(x); if (idx !== -1) { xs.splice(idx, 1); } } exports.remove = remove; /** * @remark inplace update * @return original array * */ function removeBy(xs, f) { for (let i = 0; i < xs.length; i++) { if (f(xs[i])) { xs.splice(i, 1); return xs; } } return xs; } exports.removeBy = removeBy; function nodup(xs) { const s = new Set(); xs.forEach(x => s.add(x)); return Array.from(s.values()); } exports.nodup = nodup; /** * inplace delete all duplicated element from the array (only one copy is kept) * @return old array * */ function removeDup(xs) { const ys = nodup(xs); clearArray(xs); xs.push(...ys); return xs; } exports.removeDup = removeDup; /** * inplace insert elements into the array * @return old array * */ function insertNoDup(acc, newXs) { acc.push(...newXs); return removeDup(acc); } exports.insertNoDup = insertNoDup; /** * inplace insert elements into the array * @return old array * */ function insertNoDupWithKey(acc, newXs, key) { newXs.forEach(newX => { if (!acc.find(x => x[key] === newX[key])) { acc.push(newX); } }); return acc; } exports.insertNoDupWithKey = insertNoDupWithKey; /** * inplace operation * @return old array * */ function removeDupByKey(xs, key) { const t = {}; xs.map(x => (t[x[key]] = x)); replaceArray(xs, lang_1.objValues(t)); return xs; } exports.removeDupByKey = removeDupByKey; /** * inplace update * @return old array * */ function removeByKey(xs, key, keys) { return replaceArray(xs, xs.filter(x => !array_contains(keys, x[key]))); } exports.removeByKey = removeByKey; /** * including end * */ function range(start, end, step = 1) { const res = []; for (let i = start; i <= end; i += step) { res.push(i); } return res; } exports.range = range; function repeat(x, n) { const xs = new Array(n); xs.fill(x); return xs; } exports.repeat = repeat; function filterByKey(src, key, keys) { return src.filter(x => keys.indexOf(x[key]) !== -1); } exports.filterByKey = filterByKey; function toArray(xs) { // return mapI(i => xs[i], xs.length); return Array.prototype.concat.apply([], xs); } exports.toArray = toArray; function flatten(xss) { return [].concat(...xss); } exports.flatten = flatten; /** * array.push is not monadic, this is a wrapper to make it monadic * */ function push(res, ...xs) { res.push(...xs); return res; } exports.push = push; function binArray(xs, binSize) { const res = []; let acc = []; for (const x of xs) { if (acc.length >= binSize) { res.push(acc); acc = []; } acc.push(x); } if (acc.length !== 0) { res.push(acc); } return res; } exports.binArray = binArray; /** * non-curry version of `groupBy` in functional.ts * */ function binArrayBy(xs, mapper) { const res = new Map(); for (const x of xs) { const k = mapper(x); const xs = res.get(k); if (xs) { xs.push(x); } else { res.set(k, [x]); } } return res; } exports.binArrayBy = binArrayBy; function partitionArrayBy(xs, f) { const true_xs = []; const false_xs = []; for (const x of xs) { if (f(x)) { true_xs.push(x); } else { false_xs.push(x); } } return [true_xs, false_xs]; } exports.partitionArrayBy = partitionArrayBy; function zipArray(a, b) { const res = new Array(Math.min(a.length, b.length)); for (let i = 0; i < res.length; i++) { res[i] = [a[i], b[i]]; } return res; } exports.zipArray = zipArray; /** * @description not same as Array.prototype.map! * this will not skip uninitialized items * * Compare: * new Array(3).map(x=>1) ~~> [<3 empty items>] * map(new Array(3),x=>1) ~~> [ 1, 1, 1 ] * */ function mapArray(xs, f) { const res = new Array(xs.length); for (let i = xs.length - 1; i >= 0; i--) { res[i] = f(xs[i], i, xs); } return res; } exports.mapArray = mapArray; function countArray(xs, f) { let acc = 0; const n = xs.length; for (let i = 0; i < n; i++) { if (f(xs[i], i, xs)) { acc++; } } return acc; } exports.countArray = countArray; function asyncCountArray(xs, f) { let acc = 0; return Promise.all(xs.map((x, i, xs) => f(x, i, xs).then(b => (acc += b ? 1 : 0)))).then(() => acc); } exports.asyncCountArray = asyncCountArray; function max(xs) { const n = xs.length; let acc = xs[0]; for (let i = 1; i < n; i++) { const c = xs[i]; if (acc < c) { acc = c; } } return acc; } exports.max = max; function min(xs) { const n = xs.length; let acc = xs[0]; for (let i = 1; i < n; i++) { const c = xs[i]; if (acc > c) { acc = c; } } return acc; } exports.min = min; function sum(xs) { let acc = 0; const n = xs.length; for (let i = 0; i < n; i++) { acc += xs[i]; } return acc; } exports.sum = sum; function sumByFunc(xs, mapper) { let acc = 0; const n = xs.length; for (let i = 0; i < n; i++) { acc += mapper(xs[i]); } return acc; } exports.sumByFunc = sumByFunc; function maxByFunc(xs, comparator) { let acc = xs[0]; const n = xs.length; for (let i = 1; i < n; i++) { const c = xs[i]; if (comparator(acc, c) < 0) { acc = c; } } return acc; } exports.maxByFunc = maxByFunc; function minByFunc(xs, comparator) { let acc = xs[0]; const n = xs.length; for (let i = 1; i < n; i++) { const c = xs[i]; if (comparator(acc, c) > 0) { acc = c; } } return acc; } exports.minByFunc = minByFunc; function maxByField(xs, key) { let acc = xs[0]; const n = xs.length; for (let i = 1; i < n; i++) { const c = xs[i]; if (exports.defaultComparator(acc[key], c[key]) < 0) { acc = c; } } return acc; } exports.maxByField = maxByField; function minByField(xs, key) { let acc = xs[0]; const n = xs.length; for (let i = 1; i < n; i++) { const c = xs[i]; if (exports.defaultComparator(acc[key], c[key]) > 0) { acc = c; } } return acc; } exports.minByField = minByField; function sumByField(xs, key) { let acc = 0; const n = xs.length; for (let i = 0; i < n; i++) { acc += xs[i][key]; } return acc; } exports.sumByField = sumByField; /** * side-effect: the array will be sorted in-place if instructed * * default will sort the array * */ function median(xs, options) { if (xs.length === 0) { return undefined; } if (xs.length === 1) { return xs[0]; } if (!options || options.sort !== false) { xs.sort(options && typeof options.sort === 'function' ? options.sort : exports.defaultComparator); } const n = xs.length; if (n % 2) { /* odd number */ return xs[(n - 1) / 2]; } /* even number */ const m = n / 2; const a = xs[m - 1]; const b = xs[m]; if (typeof a === 'number' && typeof b === 'number') { return ((a + b) / 2.0); } if (options && options.merger) { return options.merger(a, b); } throw new Error('cannot find median of even array'); } exports.median = median; function countElement(xs, x) { let acc = 0; const n = xs.length; for (let i = 1; i < n; i++) { if (xs[i] === x) { acc++; } } return acc; } exports.countElement = countElement; function countAll(xs) { const counts = new Map(); xs.forEach(x => map_1.incMap(counts, x)); return counts; } exports.countAll = countAll; function mode(xs) { const counts = Array.from(countAll(xs).entries()); if (counts.length === 0) { return undefined; } const maxCount = maxByField(counts, 1); return maxCount ? maxCount[0] : undefined; } exports.mode = mode; function shuffle(xs, n = xs.length) { xs = xs.slice(); for (let i = 0; i < n; i++) { const a = i; const b = random_1.Random.nextInt(n); const t = xs[a]; xs[a] = xs[b]; xs[b] = t; } return xs; } exports.shuffle = shuffle; function shuffledBinArray(xs, binSize, nSwap) { return binArray(shuffle(xs, nSwap), binSize); } exports.shuffledBinArray = shuffledBinArray; function shuffledIndices(n) { return shuffle(range(0, n - 1)); } exports.shuffledIndices = shuffledIndices; /**@deprecated typo in function name, renamed to shuffledIndices*/ exports.shuffledIndecies = shuffledIndices; /** * TODO assign a better name * e.g. f [a,b,c] 1 ~~> [[a],[b],[c]] * e.g. f [a,b,c] 2 ~~> [ [a,a],[a,b],[a,c], * [b,a],[b,b],[b,c], * [c,a],[c,b],[c,c] ] * */ function genCombination(cs, size) { if (size < 1) { return []; } let xss = cs.map(c => [c]); let i = 1; for (;;) { if (i === size) { return xss; } i++; const acc = []; const n = xss.length; for (let x = 0; x < n; x++) { const n = cs.length; for (let c = 0; c < n; c++) { const xs = xss[x].slice(); xs.push(cs[c]); acc.push(xs); } } xss = acc; } } exports.genCombination = genCombination; function flattenAll(xs) { const ys = []; flattenIoList(xs, ys); return ys; } exports.flattenAll = flattenAll; function flattenIoList(xs, ys) { const n = xs.length; for (let i = 0; i < n; i++) { const x = xs[i]; if (Array.isArray(x)) { flattenIoList(x, ys); } else { ys.push(x); } } } function _getMaxArraySize() { let i = 1; try { for (;;) { /* tslint:disable:no-unused-expression */ new Array(i); /* tslint:enable:no-unused-expression */ i += i; } } catch (e) { let min = i / 2; let max = i; for (; min + 1 < max;) { const m = Math.round((min + max) / 2); try { /* tslint:disable:no-unused-expression */ new Array(m); /* tslint:enable:no-unused-expression */ min = m; } catch (e) { max = m; } } return min; } } let MaxArraySize; function getMaxArraySize() { if (!MaxArraySize) { MaxArraySize = _getMaxArraySize(); } return MaxArraySize; } exports.getMaxArraySize = getMaxArraySize; function pushForward(xs, x) { const idx = xs.indexOf(x); if (idx === -1) { xs.unshift(x); return; } if (idx === 0) { return; // already at head } const t = xs[idx - 1]; xs[idx - 1] = x; xs[idx] = t; } exports.pushForward = pushForward; function pushBackward(xs, x) { const idx = xs.indexOf(x); if (idx === -1) { xs.push(x); return; } if (idx === xs.length - 1) { return; // already at tail } const t = xs[idx + 1]; xs[idx + 1] = x; xs[idx] = t; } exports.pushBackward = pushBackward; //# sourceMappingURL=array.js.map