@codibre/fluent-iterable
Version:
Provides LINQ-like fluent api operations for iterables and async iterables (ES2018+).
67 lines (66 loc) • 2.87 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.incPredicate = incPredicate;
exports.distinctRecipe = distinctRecipe;
const utils_1 = require("../utils");
const types_internal_1 = require("../types-internal");
const ordered_operation_recipe_1 = require("./ordered-operation-recipe");
const prepare_1 = require("../types-internal/prepare");
function inc(map, y) {
const result = (map.get(y) || 0) + 1;
map.set(y, result);
return result;
}
function incPredicate(resolver, mapper, maxOcurrences) {
const map = new Map();
return (x) => resolver(mapper(x), (y) => inc(map, y) <= maxOcurrences);
}
const nonChosen = Symbol('nonChosen');
function orderedDistinctRecipe({ map, resolver, partition, filterOrAll, hasLessOrExactly, reduce, }) {
const ordered = (0, ordered_operation_recipe_1.orderedOperationRecipe)(map, resolver, partition);
return function distinct(mapper, choose, maxOcurrences) {
const partitioned = map.call(ordered.call(this, mapper), (x) => map.call(x, (y) => y[1]));
if (typeof choose === 'function') {
return map.call(partitioned, (x) => reduce.call(x, (acc, y) => {
return acc === nonChosen ? y : choose(acc, y);
}, nonChosen));
}
return filterOrAll.call(partitioned, (part) => hasLessOrExactly.call(part, maxOcurrences));
};
}
function chooseDistinctRecipe({ forEach, resolver }) {
return function distinct(mapper, choose) {
const map = new Map();
return resolver(forEach.call(this, (x) => {
const k = mapper(x);
const old = map.get(k);
const newOne = old === undefined ? x : choose(old, x);
if (old !== newOne) {
map.set(k, newOne);
}
}), () => map.values());
};
}
function distinctRecipe(ingredients) {
const ordered = orderedDistinctRecipe(ingredients);
const choose = chooseDistinctRecipe(ingredients);
const { filterOrAll, resolver } = ingredients;
return function distinct(baseMapper = utils_1.identity, maxOcurrencesOrChoose, maxOcurrences = 1) {
const typeCheck = typeof maxOcurrencesOrChoose;
if (typeof baseMapper === 'number') {
maxOcurrences = baseMapper;
baseMapper = utils_1.identity;
}
else if (typeCheck === 'number') {
maxOcurrences = maxOcurrencesOrChoose;
}
const mapper = (0, prepare_1.prepare)(baseMapper);
if ((0, types_internal_1.isAnyOrderAssured)(mapper, this)) {
return ordered.call(this, mapper, maxOcurrencesOrChoose, maxOcurrences);
}
if (typeCheck !== 'function') {
return filterOrAll.call(this, incPredicate(resolver, mapper, maxOcurrences));
}
return choose.call(this, mapper, maxOcurrencesOrChoose);
};
}