UNPKG

@softwareventures/array

Version:

Pure functional array manipulation and traversal

1,209 lines 41.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fold = exports.removeFirstFn = exports.removeFirst = exports.removeFn = exports.remove = exports.excludeFirstFn = exports.excludeFirst = exports.excludeNull = exports.excludeFn = exports.exclude = exports.filterFn = exports.filter = exports.mapFn = exports.map = exports.prefixMatchFn = exports.prefixMatch = exports.notEqualFn = exports.notEqual = exports.equalFn = exports.equal = exports.dropUntilFn = exports.dropUntil = exports.dropWhileFn = exports.dropWhile = exports.takeUntilFn = exports.takeUntil = exports.takeWhileFn = exports.takeWhile = exports.dropFn = exports.drop = exports.takeFn = exports.take = exports.sliceFn = exports.slice = exports.reverse = exports.notEmpty = exports.empty = exports.only = exports.last = exports.initial = exports.unshiftFn = exports.unshift = exports.pushFn = exports.push = exports.tail = exports.first = exports.coerce = exports.isArrayLike = exports.isArray = exports.copy = void 0; exports.scanFn = exports.scan = exports.noneNull = exports.concatMapFn = exports.concatMap = exports.append = exports.prepend = exports.concat = exports.allFn = exports.all = exports.anyFn = exports.any = exports.or = exports.and = exports.average = exports.product = exports.sum = exports.minimumByFn = exports.minimumBy = exports.minimumFn = exports.minimum = exports.maximumByFn = exports.maximumBy = exports.maximumFn = exports.maximum = exports.findLastFn = exports.findLast = exports.findFn = exports.find = exports.findLastIndexFn = exports.findLastIndex = exports.findIndexFn = exports.findIndex = exports.lastIndexOfFn = exports.lastIndexOf = exports.indexOfFn = exports.indexOf = exports.containsFn = exports.contains = exports.foldMapRightFn = exports.foldMapRight = exports.foldMapFn = exports.foldMap = exports.foldRight1Fn = exports.foldRight1 = exports.foldRightFn = exports.foldRight = exports.fold1Fn = exports.fold1 = exports.foldFn = void 0; exports.groupAdjacentByOrderFn = exports.groupAdjacentByOrder = exports.groupAdjacentByEqualityFn = exports.groupAdjacentByEquality = exports.groupAdjacentByIdentityFn = exports.groupAdjacentByIdentity = exports.groupAdjacentFn = exports.groupAdjacent = exports.groupByOrderWithHashFn = exports.groupByOrderWithHash = exports.groupByEqualityWithHashFn = exports.groupByEqualityWithHash = exports.groupByHashFn = exports.groupByHash = exports.groupByOrderFn = exports.groupByOrder = exports.groupByEqualityFn = exports.groupByEquality = exports.groupByIdentityFn = exports.groupByIdentity = exports.groupFn = exports.group = exports.mapKeyLastByFn = exports.mapKeyLastBy = exports.mapKeyFirstByFn = exports.mapKeyFirstBy = exports.mapKeyByFn = exports.mapKeyBy = exports.keyLastByFn = exports.keyLastBy = exports.keyFirstByFn = exports.keyFirstBy = exports.keyByFn = exports.keyBy = exports.zipFn = exports.zip = exports.partitionUntilFn = exports.partitionUntil = exports.partitionWhileFn = exports.partitionWhile = exports.partitionFn = exports.partition = exports.splitFn = exports.split = exports.scanRight1Fn = exports.scanRight1 = exports.scanRightFn = exports.scanRight = exports.scan1Fn = exports.scan1 = void 0; exports.forEachFn = exports.forEach = exports.sortByDescendingFn = exports.sortByDescending = exports.sortByFn = exports.sortBy = exports.sortFn = exports.sort = exports.uniqueAdjacentByHashFn = exports.uniqueAdjacentByHash = exports.uniqueAdjacentByOrderFn = exports.uniqueAdjacentByOrder = exports.uniqueAdjacentByEqualityFn = exports.uniqueAdjacentByEquality = exports.uniqueAdjacentByIdentityFn = exports.uniqueAdjacentByIdentity = exports.uniqueAdjacentFn = exports.uniqueAdjacent = exports.uniqueByOrderWithHashFn = exports.uniqueByOrderWithHash = exports.uniqueByEqualityWithHashFn = exports.uniqueByEqualityWithHash = exports.uniqueByHashFn = exports.uniqueByHash = exports.uniqueByOrderFn = exports.uniqueByOrder = exports.uniqueByEqualityFn = exports.uniqueByEquality = exports.uniqueByIdentity = exports.uniqueFn = exports.unique = exports.groupAdjacentByHashFn = exports.groupAdjacentByHash = void 0; const nullable_1 = require("@softwareventures/nullable"); const ordered_1 = require("@softwareventures/ordered"); // eslint-disable-next-line @typescript-eslint/unbound-method const nativeSlice = Array.prototype.slice; // eslint-disable-next-line @typescript-eslint/unbound-method const nativeReverse = Array.prototype.reverse; // eslint-disable-next-line @typescript-eslint/unbound-method const nativeConcat = Array.prototype.concat; // eslint-disable-next-line @typescript-eslint/unbound-method const nativeFilter = Array.prototype.filter; // eslint-disable-next-line @typescript-eslint/unbound-method const nativeReduce = Array.prototype.reduce; // eslint-disable-next-line @typescript-eslint/unbound-method const nativeReduceRight = Array.prototype.reduceRight; // eslint-disable-next-line @typescript-eslint/unbound-method const nativeIndexOf = Array.prototype.indexOf; // eslint-disable-next-line @typescript-eslint/unbound-method const nativeFindIndex = Array.prototype.findIndex; /** @internal This implementation is for internal use only, the exported declaration is above */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore duplicate identifier: This is the actual implementation, the exported declaration is above. exports.copy = Array.from; /** @internal This implementation is for internal use only, the exported declaration is above */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore duplicate identifier: This is the actual implementation, the exported declaration is above. exports.isArray = Array.isArray; // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents function isArrayLike(value) { return (typeof value === "object" && value != null && "length" in value && typeof value.length === "number"); } exports.isArrayLike = isArrayLike; function coerce(array) { return (0, exports.isArray)(array) ? array : (0, exports.copy)(array); } exports.coerce = coerce; function first(array) { return array.length === 0 ? null : array[0]; } exports.first = first; function tail(array) { return nativeSlice.call(array, 1); } exports.tail = tail; function push(array, value) { return [...coerce(array), value]; } exports.push = push; function pushFn(value) { return array => push(array, value); } exports.pushFn = pushFn; function unshift(array, value) { return [value, ...coerce(array)]; } exports.unshift = unshift; function unshiftFn(value) { return array => unshift(array, value); } exports.unshiftFn = unshiftFn; function initial(array) { return array.length === 0 ? [] : nativeSlice.call(array, 0, array.length - 1); } exports.initial = initial; function last(array) { return array.length === 0 ? null : array[array.length - 1]; } exports.last = last; /** If the array contains exactly one element, returns that element. * Otherwise, returns null. */ function only(array) { return array.length === 1 ? array[0] : null; } exports.only = only; function empty(array) { return array.length === 0; } exports.empty = empty; function notEmpty(array) { return array.length > 0; } exports.notEmpty = notEmpty; function reverse(array) { return nativeReverse.call((0, exports.copy)(array)); } exports.reverse = reverse; function slice(array, start, end) { return nativeSlice.call(array, start, end); } exports.slice = slice; function sliceFn(start, end) { return array => nativeSlice.call(array, start, end); } exports.sliceFn = sliceFn; function take(array, count) { return nativeSlice.call(array, 0, count); } exports.take = take; function takeFn(count) { return array => nativeSlice.call(array, 0, count); } exports.takeFn = takeFn; function drop(array, count) { return nativeSlice.call(array, count); } exports.drop = drop; function dropFn(count) { return array => nativeSlice.call(array, count); } exports.dropFn = dropFn; function takeWhile(array, predicate) { let i = 0; while (i < array.length && predicate(array[i], i)) { ++i; } return take(array, i); } exports.takeWhile = takeWhile; function takeWhileFn(predicate) { return array => takeWhile(array, predicate); } exports.takeWhileFn = takeWhileFn; function takeUntil(array, predicate) { return takeWhile(array, (element, index) => !predicate(element, index)); } exports.takeUntil = takeUntil; function takeUntilFn(predicate) { return array => takeUntil(array, predicate); } exports.takeUntilFn = takeUntilFn; function dropWhile(array, predicate) { let i = 0; while (i < array.length && predicate(array[i], i)) { ++i; } return drop(array, i); } exports.dropWhile = dropWhile; function dropWhileFn(predicate) { return array => dropWhile(array, predicate); } exports.dropWhileFn = dropWhileFn; function dropUntil(array, predicate) { return dropWhile(array, (element, index) => !predicate(element, index)); } exports.dropUntil = dropUntil; function dropUntilFn(predicate) { return array => dropWhile(array, predicate); } exports.dropUntilFn = dropUntilFn; function equal(a, b, elementsEqual = ordered_1.equal) { if (a.length !== b.length) { return false; } for (let i = 0; i < a.length; ++i) { if (!elementsEqual(a[i], b[i])) { return false; } } return true; } exports.equal = equal; function equalFn(b, elementsEqual = ordered_1.equal) { return a => equal(a, b, elementsEqual); } exports.equalFn = equalFn; function notEqual(a, b, elementsEqual = ordered_1.equal) { return !equal(a, b, elementsEqual); } exports.notEqual = notEqual; function notEqualFn(b, elementsEqual = ordered_1.equal) { return a => notEqual(a, b, elementsEqual); } exports.notEqualFn = notEqualFn; function prefixMatch(a, b, elementsEqual = ordered_1.equal) { if (a.length < b.length) { return false; } for (let i = 0; i < b.length; ++i) { if (a[i] !== b[i]) { return false; } } return true; } exports.prefixMatch = prefixMatch; function prefixMatchFn(b, elementsEqual = ordered_1.equal) { return a => prefixMatch(a, b, elementsEqual); } exports.prefixMatchFn = prefixMatchFn; /** @internal This implementation is for internal use only, the exported declaration is above */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore duplicate identifier: This is the actual implementation, the exported declaration is above. exports.map = Array.from; function mapFn(f) { return array => Array.from(array, f); } exports.mapFn = mapFn; function filter(array, predicate) { return nativeFilter.call(array, predicate); } exports.filter = filter; function filterFn(predicate) { return array => nativeFilter.call(array, predicate); } exports.filterFn = filterFn; function exclude(array, predicate) { return filter(array, (element, index) => !predicate(element, index)); } exports.exclude = exclude; function excludeFn(predicate) { return array => exclude(array, predicate); } exports.excludeFn = excludeFn; function excludeNull(array) { return filter(array, nullable_1.isNotNull); } exports.excludeNull = excludeNull; function excludeFirst(array, predicate) { const result = []; let i = 0; for (; i < array.length; ++i) { const element = array[i]; if (!predicate(element, i)) { result.push(element); } else { break; } } for (++i; i < array.length; ++i) { result.push(array[i]); } return result; } exports.excludeFirst = excludeFirst; function excludeFirstFn(predicate) { return array => excludeFirst(array, predicate); } exports.excludeFirstFn = excludeFirstFn; function remove(array, value) { return exclude(array, element => element === value); } exports.remove = remove; function removeFn(value) { return array => remove(array, value); } exports.removeFn = removeFn; function removeFirst(array, value) { return excludeFirst(array, element => element === value); } exports.removeFirst = removeFirst; function removeFirstFn(value) { return array => removeFirst(array, value); } exports.removeFirstFn = removeFirstFn; function fold(array, f, initial) { return nativeReduce.call(array, f, initial); } exports.fold = fold; function foldFn(f, initial) { return array => nativeReduce.call(array, f, initial); } exports.foldFn = foldFn; function fold1(array, f) { return nativeReduce.call(array, f); } exports.fold1 = fold1; function fold1Fn(f) { return array => fold1(array, f); } exports.fold1Fn = fold1Fn; function foldRight(array, f, initial) { return nativeReduceRight.call(array, f, initial); } exports.foldRight = foldRight; function foldRightFn(f, initial) { return array => nativeReduceRight.call(array, f, initial); } exports.foldRightFn = foldRightFn; function foldRight1(array, f) { return nativeReduceRight.call(array, f); } exports.foldRight1 = foldRight1; function foldRight1Fn(f) { return array => foldRight1(array, f); } exports.foldRight1Fn = foldRight1Fn; function foldMap(array, f, m, initial) { let accumulator = initial; for (let i = 0; i < array.length; ++i) { accumulator = f(accumulator, m(array[i], i), i); } return accumulator; } exports.foldMap = foldMap; function foldMapFn(f, m, initial) { return array => foldMap(array, f, m, initial); } exports.foldMapFn = foldMapFn; function foldMapRight(array, f, m, initial) { let accumulator = initial; const length = array.length; for (let i = 0; i < array.length; ++i) { accumulator = f(accumulator, m(array[length - i], i), i); } return accumulator; } exports.foldMapRight = foldMapRight; function foldMapRightFn(f, m, initial) { return array => foldMapRight(array, f, m, initial); } exports.foldMapRightFn = foldMapRightFn; function contains(array, value) { return nativeIndexOf.call(array, value) !== -1; } exports.contains = contains; function containsFn(value) { return array => nativeIndexOf.call(array, value) !== -1; } exports.containsFn = containsFn; function indexOf(array, value) { const index = nativeIndexOf.call(array, value); return index === -1 ? null : index; } exports.indexOf = indexOf; function indexOfFn(value) { return array => indexOf(array, value); } exports.indexOfFn = indexOfFn; function lastIndexOf(array, value) { for (let i = array.length - 1; i >= 0; --i) { if (array[i] === value) { return i; } } return null; } exports.lastIndexOf = lastIndexOf; function lastIndexOfFn(value) { return array => lastIndexOf(array, value); } exports.lastIndexOfFn = lastIndexOfFn; function findIndex(array, predicate) { const index = nativeFindIndex.call(array, predicate); return index === -1 ? null : index; } exports.findIndex = findIndex; function findIndexFn(predicate) { return array => findIndex(array, predicate); } exports.findIndexFn = findIndexFn; function findLastIndex(array, predicate) { for (let i = array.length - 1; i >= 0; --i) { if (predicate(array[i], i)) { return i; } } return null; } exports.findLastIndex = findLastIndex; function findLastIndexFn(predicate) { return array => findLastIndex(array, predicate); } exports.findLastIndexFn = findLastIndexFn; function find(array, predicate) { const index = findIndex(array, predicate); return index == null ? null : array[index]; } exports.find = find; function findFn(predicate) { return array => find(array, predicate); } exports.findFn = findFn; function findLast(array, predicate) { for (let i = array.length - 1; i >= 0; --i) { const element = array[i]; if (predicate(element, i)) { return element; } } return null; } exports.findLast = findLast; function findLastFn(predicate) { return array => findLast(array, predicate); } exports.findLastFn = findLastFn; function maximum(array, compare) { return internalMaximum(array, compare !== null && compare !== void 0 ? compare : ordered_1.compare); } exports.maximum = maximum; function maximumFn(compare) { return array => internalMaximum(array, compare !== null && compare !== void 0 ? compare : ordered_1.compare); } exports.maximumFn = maximumFn; function internalMaximum(array, compare) { if (array.length === 0) { return null; } let result = array[0]; for (let i = 1; i < array.length; ++i) { if (compare(array[i], result) > ordered_1.Comparison.equal) { result = array[i]; } } return result; } function maximumBy(array, select) { return maximum(array, (a, b) => (0, ordered_1.compare)(select(a), select(b))); } exports.maximumBy = maximumBy; function maximumByFn(select) { return array => maximumBy(array, select); } exports.maximumByFn = maximumByFn; function minimum(array, compare) { return internalMinimum(array, compare !== null && compare !== void 0 ? compare : ordered_1.compare); } exports.minimum = minimum; function minimumFn(compare) { return array => internalMinimum(array, compare !== null && compare !== void 0 ? compare : ordered_1.compare); } exports.minimumFn = minimumFn; function internalMinimum(array, compare) { if (array.length === 0) { return null; } let result = array[0]; for (let i = 1; i < array.length; ++i) { if (compare(array[i], result) < ordered_1.Comparison.equal) { result = array[i]; } } return result; } function minimumBy(array, select) { return minimum(array, (a, b) => (0, ordered_1.compare)(select(a), select(b))); } exports.minimumBy = minimumBy; function minimumByFn(select) { return array => minimumBy(array, select); } exports.minimumByFn = minimumByFn; function sum(array) { return fold(array, (a, b) => a + b, 0); } exports.sum = sum; function product(array) { return fold(array, (a, b) => a * b, 1); } exports.product = product; function average(array) { if (array.length === 0) { return null; } else { return sum(array) / array.length; } } exports.average = average; function and(array) { return findIndex(array, element => !element) == null; } exports.and = and; function or(array) { return findIndex(array, element => Boolean(element)) != null; } exports.or = or; function any(array, predicate) { return findIndex(array, predicate) != null; } exports.any = any; function anyFn(predicate) { return array => any(array, predicate); } exports.anyFn = anyFn; function all(array, predicate) { return !any(array, (element, index) => !predicate(element, index)); } exports.all = all; function allFn(predicate) { return array => all(array, predicate); } exports.allFn = allFn; function concat(arrays) { return nativeConcat.apply([], (0, exports.map)(arrays, coerce)); } exports.concat = concat; function prepend(a) { return b => concat([a, b]); } exports.prepend = prepend; function append(b) { return a => concat([a, b]); } exports.append = append; function concatMap(array, f) { return concat((0, exports.map)(array, f)); } exports.concatMap = concatMap; function concatMapFn(f) { return array => concatMap(array, f); } exports.concatMapFn = concatMapFn; function noneNull(array) { return any(array, nullable_1.isNull) ? null : array; } exports.noneNull = noneNull; function scan(array, f, initial) { const result = (0, exports.copy)({ length: array.length }); let accumulator = initial; for (let i = 0; i < array.length; ++i) { result[i] = accumulator = f(accumulator, array[i], i); } return result; } exports.scan = scan; function scanFn(f, initial) { return array => scan(array, f, initial); } exports.scanFn = scanFn; function scan1(array, f) { if (array.length === 0) { return []; } let accumulator = array[0]; const result = (0, exports.copy)({ 0: accumulator, length: array.length }); for (let i = 1; i < array.length; ++i) { result[i] = accumulator = f(accumulator, array[i], i); } return result; } exports.scan1 = scan1; function scan1Fn(f) { return array => scan1(array, f); } exports.scan1Fn = scan1Fn; function scanRight(array, f, initial) { const result = (0, exports.copy)({ length: array.length }); let accumulator = initial; for (let i = array.length - 1; i >= 0; --i) { result[i] = accumulator = f(accumulator, array[i], i); } return result; } exports.scanRight = scanRight; function scanRightFn(f, initial) { return array => scanRight(array, f, initial); } exports.scanRightFn = scanRightFn; function scanRight1(array, f) { if (array.length === 0) { return []; } let accumulator = array[array.length - 1]; const result = (0, exports.copy)({ [array.length - 1]: accumulator, length: array.length }); for (let i = array.length - 2; i >= 0; --i) { result[i] = accumulator = f(accumulator, array[i], i); } return result; } exports.scanRight1 = scanRight1; function scanRight1Fn(f) { return array => scanRight1(array, f); } exports.scanRight1Fn = scanRight1Fn; /** Splits the array at the specified index. * * Returns a tuple where the first element is the first `index` elements of the * array, and the second element is the remaining elements of the array. */ function split(array, index) { return [take(array, index), drop(array, index)]; } exports.split = split; /** Returns a function that splits an array at the specified index. * * This is the curried form of {@link split}. */ function splitFn(index) { return array => split(array, index); } exports.splitFn = splitFn; function partition(array, predicate) { const a = []; const b = []; for (let i = 0; i < array.length; ++i) { if (predicate(array[i], i)) { a.push(array[i]); } else { b.push(array[i]); } } return [a, b]; } exports.partition = partition; function partitionFn(predicate) { return array => partition(array, predicate); } exports.partitionFn = partitionFn; function partitionWhile(array, predicate) { let i; for (i = 0; i < array.length; ++i) { if (!predicate(array[i], i)) { break; } } return [take(array, i), drop(array, i)]; } exports.partitionWhile = partitionWhile; function partitionWhileFn(predicate) { return array => partitionWhile(array, predicate); } exports.partitionWhileFn = partitionWhileFn; function partitionUntil(array, predicate) { return partitionWhile(array, element => !predicate(element)); } exports.partitionUntil = partitionUntil; function partitionUntilFn(predicate) { return array => partitionUntil(array, predicate); } exports.partitionUntilFn = partitionUntilFn; /** Takes two arrays and returns an array of corresponding pairs. * * If one of the supplied arrays is shorter than the other, then the excess * elements of the longer array will be discarded. */ function zip(a, b) { const length = Math.min(a.length, b.length); const result = new Array(length); for (let i = 0; i < length; ++i) { result[i] = [a[i], b[i]]; } return result; } exports.zip = zip; /** Returns a function that combines the elements of `a` with the elements of * `b` and returns an array of corresponding pairs. * * If one of the supplied arrays is shorter than the other, then the excess * elements of the longer array will be discarded. * * This is the curried variant of {@link zip}. */ function zipFn(b) { return a => zip(a, b); } exports.zipFn = zipFn; function keyBy(array, f) { var _a; const result = new Map(); for (let i = 0; i < array.length; ++i) { const element = array[i]; const key = f(element, i); const group = (_a = result.get(key)) !== null && _a !== void 0 ? _a : []; if (!result.has(key)) { result.set(key, group); } group.push(element); } return result; } exports.keyBy = keyBy; function keyByFn(f) { return array => keyBy(array, f); } exports.keyByFn = keyByFn; function keyFirstBy(array, f) { const result = new Map(); for (let i = 0; i < array.length; ++i) { const element = array[i]; const key = f(element, i); if (!result.has(key)) { result.set(key, element); } } return result; } exports.keyFirstBy = keyFirstBy; function keyFirstByFn(f) { return array => keyFirstBy(array, f); } exports.keyFirstByFn = keyFirstByFn; function keyLastBy(array, f) { const result = new Map(); for (let i = 0; i < array.length; ++i) { const element = array[i]; const key = f(element, i); result.set(key, element); } return result; } exports.keyLastBy = keyLastBy; function keyLastByFn(f) { return array => keyLastBy(array, f); } exports.keyLastByFn = keyLastByFn; function mapKeyBy(array, f) { var _a; const result = new Map(); for (let i = 0; i < array.length; ++i) { const [key, element] = f(array[i], i); const group = (_a = result.get(key)) !== null && _a !== void 0 ? _a : []; if (!result.has(key)) { result.set(key, group); } group.push(element); } return result; } exports.mapKeyBy = mapKeyBy; function mapKeyByFn(f) { return array => mapKeyBy(array, f); } exports.mapKeyByFn = mapKeyByFn; function mapKeyFirstBy(array, f) { const result = new Map(); for (let i = 0; i < array.length; ++i) { const [key, element] = f(array[i], i); if (!result.has(key)) { result.set(key, element); } } return result; } exports.mapKeyFirstBy = mapKeyFirstBy; function mapKeyFirstByFn(f) { return array => mapKeyFirstBy(array, f); } exports.mapKeyFirstByFn = mapKeyFirstByFn; function mapKeyLastBy(array, f) { const result = new Map(); for (let i = 0; i < array.length; ++i) { const [key, element] = f(array[i], i); result.set(key, element); } return result; } exports.mapKeyLastBy = mapKeyLastBy; function mapKeyLastByFn(f) { return array => mapKeyLastBy(array, f); } exports.mapKeyLastByFn = mapKeyLastByFn; function group(array, grouping) { if ("identity" in grouping) { return groupByIdentity(array, grouping.identity); } else if ("compare" in grouping) { if (typeof grouping.hash === "function") { return groupByOrderWithHash(array, grouping.compare, grouping.hash); } else { return groupByOrder(array, grouping.compare); } } else if ("equal" in grouping) { if (typeof grouping.hash === "function") { return groupByEqualityWithHash(array, grouping.equal, grouping.hash); } else { return groupByEquality(array, grouping.equal); } } else { return groupByHash(array, grouping.hash); } } exports.group = group; function groupFn(grouping) { return array => group(array, grouping); } exports.groupFn = groupFn; function groupByIdentity(array, identity = element => element) { var _a; const groups = []; const map = new Map(); for (let i = 0; i < array.length; ++i) { const element = array[i]; const key = identity(element); const group = (_a = map.get(key)) !== null && _a !== void 0 ? _a : []; group.push(element); if (!map.has(key)) { groups.push(group); map.set(key, group); } } return groups; } exports.groupByIdentity = groupByIdentity; function groupByIdentityFn(identity) { return array => groupByIdentity(array, identity); } exports.groupByIdentityFn = groupByIdentityFn; function groupByEquality(array, equal) { const result = []; outer: for (let i = 0; i < array.length; ++i) { for (let j = 0; j < result.length; ++j) { const group = (0, nullable_1.notNull)(result[j]); if (equal(group[0], array[i])) { group.push(array[i]); continue outer; } } result.push([array[i]]); } return result; } exports.groupByEquality = groupByEquality; function groupByEqualityFn(equal) { return array => groupByEquality(array, equal); } exports.groupByEqualityFn = groupByEqualityFn; function groupByOrder(array, compare) { // TODO: This could use a binary tree to be way more efficient return groupByEquality(array, (a, b) => compare(a, b) === ordered_1.Comparison.equal); } exports.groupByOrder = groupByOrder; function groupByOrderFn(compare) { return array => groupByOrder(array, compare); } exports.groupByOrderFn = groupByOrderFn; function groupByHash(array, hash) { var _a; const groups = new Map(); const result = []; for (let i = 0; i < array.length; ++i) { const element = array[i]; const h = hash(element, i); const group = (_a = groups.get(h)) !== null && _a !== void 0 ? _a : []; if (!groups.has(h)) { result.push(group); groups.set(h, group); } group.push(element); } return result; } exports.groupByHash = groupByHash; function groupByHashFn(hash) { return array => groupByHash(array, hash); } exports.groupByHashFn = groupByHashFn; function groupByEqualityWithHash(array, equal, hash) { var _a; const groups = new Map(); const result = []; for (let i = 0; i < array.length; ++i) { const element = array[i]; const h = hash(element, i); const hashGroup = (_a = groups.get(h)) !== null && _a !== void 0 ? _a : []; if (!groups.has(h)) { groups.set(h, hashGroup); } const group = find(hashGroup, group => equal(group[0], element)); if (group == null) { const newGroup = [element]; hashGroup.push(newGroup); result.push(newGroup); } else { group.push(element); } } return result; } exports.groupByEqualityWithHash = groupByEqualityWithHash; function groupByEqualityWithHashFn(equal, hash) { return array => groupByEqualityWithHash(array, equal, hash); } exports.groupByEqualityWithHashFn = groupByEqualityWithHashFn; function groupByOrderWithHash(array, compare, hash) { return groupByEqualityWithHash(array, (a, b) => compare(a, b) === ordered_1.Comparison.equal, hash); } exports.groupByOrderWithHash = groupByOrderWithHash; function groupByOrderWithHashFn(compare, hash) { return array => groupByOrderWithHash(array, compare, hash); } exports.groupByOrderWithHashFn = groupByOrderWithHashFn; function groupAdjacent(array, grouping) { if ("identity" in grouping) { return groupAdjacentByIdentity(array, grouping.identity); } else if ("equal" in grouping) { return groupAdjacentByEquality(array, grouping.equal); } else if ("compare" in grouping) { return groupAdjacentByOrder(array, grouping.compare); } else { return groupByHash(array, grouping.hash); } } exports.groupAdjacent = groupAdjacent; function groupAdjacentFn(grouping) { return array => groupAdjacent(array, grouping); } exports.groupAdjacentFn = groupAdjacentFn; function groupAdjacentByIdentity(array, identity) { return identity == null ? groupAdjacentByEquality(array, (a, b) => a === b) : groupAdjacentByEquality(array, (a, b) => identity(a) === identity(b)); } exports.groupAdjacentByIdentity = groupAdjacentByIdentity; function groupAdjacentByIdentityFn(identity) { return array => groupAdjacentByEquality(array, (a, b) => identity(a) === identity(b)); } exports.groupAdjacentByIdentityFn = groupAdjacentByIdentityFn; function groupAdjacentByEquality(array, equal) { if (array.length === 0) { return []; } let element = array[0]; let group = [element]; const result = [group]; for (let i = 1; i < array.length; ++i) { const prev = element; element = array[i]; if (equal(prev, element)) { group.push(element); } else { group = [element]; result.push(group); } } return result; } exports.groupAdjacentByEquality = groupAdjacentByEquality; function groupAdjacentByEqualityFn(equal) { return array => groupAdjacentByEquality(array, equal); } exports.groupAdjacentByEqualityFn = groupAdjacentByEqualityFn; function groupAdjacentByOrder(array, compare) { return groupAdjacentByEquality(array, (a, b) => compare(a, b) === ordered_1.Comparison.equal); } exports.groupAdjacentByOrder = groupAdjacentByOrder; function groupAdjacentByOrderFn(compare) { return array => groupAdjacentByOrder(array, compare); } exports.groupAdjacentByOrderFn = groupAdjacentByOrderFn; function groupAdjacentByHash(array, hash) { if (array.length === 0) { return []; } const element = array[0]; let h = hash(element, 0); let group = [element]; const result = [group]; for (let i = 1; i < array.length; ++i) { const element = array[i]; const h1 = hash(element, i); if (h === h1) { group.push(element); } else { h = h1; group = [element]; result.push(group); } } return result; } exports.groupAdjacentByHash = groupAdjacentByHash; function groupAdjacentByHashFn(hash) { return array => groupAdjacentByHash(array, hash); } exports.groupAdjacentByHashFn = groupAdjacentByHashFn; function unique(array, grouping) { if ("identity" in grouping) { return uniqueByIdentityInternal(array, grouping.identity); } else if ("compare" in grouping) { if (typeof grouping.hash === "function") { return uniqueByOrderWithHash(array, grouping.compare, grouping.hash); } else { return uniqueByOrder(array, grouping.compare); } } else if ("equal" in grouping) { if (typeof grouping.hash === "function") { return uniqueByEqualityWithHash(array, grouping.equal, grouping.hash); } else { return uniqueByEquality(array, grouping.equal); } } else { return uniqueByHash(array, grouping.hash); } } exports.unique = unique; function uniqueFn(grouping) { return array => unique(array, grouping); } exports.uniqueFn = uniqueFn; function uniqueByIdentity(array, identity) { return uniqueByIdentityInternal(array, identity !== null && identity !== void 0 ? identity : (element => element)); } exports.uniqueByIdentity = uniqueByIdentity; function uniqueByIdentityInternal(array, identity) { const set = new Set(); const result = []; for (let i = 0; i < array.length; ++i) { const element = array[i]; if (!set.has(identity(element))) { set.add(identity(element)); result.push(element); } } return result; } function uniqueByEquality(array, equal) { const result = []; outer: for (let i = 0; i < array.length; ++i) { const element = array[i]; for (let j = 0; j < result.length; ++j) { if (equal(element, result[j])) { continue outer; } } result.push(element); } return result; } exports.uniqueByEquality = uniqueByEquality; function uniqueByEqualityFn(equal) { return array => uniqueByEquality(array, equal); } exports.uniqueByEqualityFn = uniqueByEqualityFn; function uniqueByOrder(array, compare) { return uniqueByEquality(array, (a, b) => compare(a, b) === ordered_1.Comparison.equal); } exports.uniqueByOrder = uniqueByOrder; function uniqueByOrderFn(compare) { // TODO: This could use a binary tree to be more efficient return array => uniqueByOrder(array, compare); } exports.uniqueByOrderFn = uniqueByOrderFn; function uniqueByHash(array, hash) { const seen = new Set(); const result = []; for (let i = 0; i < array.length; ++i) { const element = array[i]; const h = hash(element, i); if (!seen.has(h)) { seen.add(h); result.push(element); } } return result; } exports.uniqueByHash = uniqueByHash; function uniqueByHashFn(hash) { return array => uniqueByHash(array, hash); } exports.uniqueByHashFn = uniqueByHashFn; function uniqueByEqualityWithHash(array, equal, hash) { var _a; const seenGroups = new Map(); const result = []; for (let i = 0; i < array.length; ++i) { const element = array[i]; const h = hash(element, i); const seenGroup = (_a = seenGroups.get(h)) !== null && _a !== void 0 ? _a : []; if (!seenGroups.has(h)) { seenGroups.set(h, seenGroup); } if (all(seenGroup, seenElement => !equal(seenElement, element))) { seenGroup.push(element); result.push(element); } } return result; } exports.uniqueByEqualityWithHash = uniqueByEqualityWithHash; function uniqueByEqualityWithHashFn(equal, hash) { return array => uniqueByEqualityWithHash(array, equal, hash); } exports.uniqueByEqualityWithHashFn = uniqueByEqualityWithHashFn; function uniqueByOrderWithHash(array, compare, hash) { return uniqueByEqualityWithHash(array, (a, b) => compare(a, b) === ordered_1.Comparison.equal, hash); } exports.uniqueByOrderWithHash = uniqueByOrderWithHash; function uniqueByOrderWithHashFn(compare, hash) { return array => uniqueByOrderWithHash(array, compare, hash); } exports.uniqueByOrderWithHashFn = uniqueByOrderWithHashFn; function uniqueAdjacent(array, grouping) { if ("identity" in grouping) { return uniqueAdjacentByIdentity(array, grouping.identity); } else if ("equal" in grouping) { return uniqueAdjacentByEquality(array, grouping.equal); } else if ("compare" in grouping) { return uniqueAdjacentByOrder(array, grouping.compare); } else { return uniqueAdjacentByHash(array, grouping.hash); } } exports.uniqueAdjacent = uniqueAdjacent; function uniqueAdjacentFn(grouping) { return array => uniqueAdjacent(array, grouping); } exports.uniqueAdjacentFn = uniqueAdjacentFn; function uniqueAdjacentByIdentity(array, identity) { return identity == null ? uniqueAdjacentByEquality(array, (a, b) => a === b) : uniqueAdjacentByEquality(array, (a, b) => identity(a) === identity(b)); } exports.uniqueAdjacentByIdentity = uniqueAdjacentByIdentity; function uniqueAdjacentByIdentityFn(identity) { return array => uniqueAdjacentByIdentity(array, identity); } exports.uniqueAdjacentByIdentityFn = uniqueAdjacentByIdentityFn; function uniqueAdjacentByEquality(array, equal) { if (array.length === 0) { return []; } let element = array[0]; const result = [element]; for (let i = 1; i < array.length; ++i) { const prev = element; element = array[i]; if (!equal(prev, element)) { result.push(element); } } return result; } exports.uniqueAdjacentByEquality = uniqueAdjacentByEquality; function uniqueAdjacentByEqualityFn(equal) { return array => uniqueAdjacentByEquality(array, equal); } exports.uniqueAdjacentByEqualityFn = uniqueAdjacentByEqualityFn; function uniqueAdjacentByOrder(array, compare) { return uniqueAdjacentByEquality(array, (a, b) => compare(a, b) === ordered_1.Comparison.equal); } exports.uniqueAdjacentByOrder = uniqueAdjacentByOrder; function uniqueAdjacentByOrderFn(compare) { return array => uniqueAdjacentByOrder(array, compare); } exports.uniqueAdjacentByOrderFn = uniqueAdjacentByOrderFn; function uniqueAdjacentByHash(array, hash) { if (array.length === 0) { return []; } const element = array[0]; let h = hash(element, 0); const result = [element]; for (let i = 1; i < array.length; ++i) { const element = array[i]; const h1 = hash(element, i); if (h !== h1) { h = h1; result.push(element); } } return result; } exports.uniqueAdjacentByHash = uniqueAdjacentByHash; function uniqueAdjacentByHashFn(hash) { return array => uniqueAdjacentByHash(array, hash); } exports.uniqueAdjacentByHashFn = uniqueAdjacentByHashFn; function sort(array, comparator) { return (0, exports.copy)(array).sort(comparator !== null && comparator !== void 0 ? comparator : ordered_1.compare); } exports.sort = sort; function sortFn(comparator) { return array => sort(array, comparator); } exports.sortFn = sortFn; function sortBy(array, select) { return sort(array, (a, b) => ordered_1.compare(select(a), select(b))); } exports.sortBy = sortBy; function sortByFn(select) { return array => sortBy(array, select); } exports.sortByFn = sortByFn; function sortByDescending(array, select) { return sort(array, (a, b) => -ordered_1.compare(select(a), select(b))); } exports.sortByDescending = sortByDescending; function sortByDescendingFn(select) { return array => sortByDescending(array, select); } exports.sortByDescendingFn = sortByDescendingFn; function forEach(array, f) { for (let i = 0; i < array.length; ++i) { f(array[i], i); } return array; } exports.forEach = forEach; function forEachFn(f) { return array => forEach(array, f); } exports.forEachFn = forEachFn; //# sourceMappingURL=index.js.map