@codibre/fluent-iterable
Version:
Provides LINQ-like fluent api operations for iterables and async iterables (ES2018+).
59 lines (58 loc) • 2.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.combineRecipe = combineRecipe;
const prepare_1 = require("../types-internal/prepare");
const utils_1 = require("../utils");
function getMapItems(m, keyB, resolver) {
return (u) => resolver(keyB(u), (key) => {
let p = m.get(key);
if (!p) {
p = [];
m.set(key, p);
}
p.push(u);
return m;
});
}
function getMapResult(m, keyA, resolver) {
return (t) => resolver(keyA(t), (key) => {
const result = m.get(key);
return result !== undefined ? result.map((u) => [t, u]) : undefined;
});
}
function getMapNN(cache, map) {
return ([a, bIt]) => cache.length > 0
? map.call(cache, (b) => [a, b])
: map.call(bIt, (b) => {
cache.push(b);
return [a, b];
});
}
function getCombineNN(map, flatten) {
return function (itThis, iterable) {
const cache = [];
const mapped = map.call(itThis, (a) => [a, iterable]);
return flatten.call(mapped, getMapNN(cache, map));
};
}
function getInnerJoin({ resolver, flatten, forEach, filter, map, }) {
return function (itThis, iterable, baseKeyA, baseKeyB) {
const keyA = (0, prepare_1.prepare)(baseKeyA);
const keyB = (0, prepare_1.prepare)(baseKeyB);
const m = new Map();
return resolver(forEach.call(iterable, getMapItems(m, keyB, resolver)), () => flatten.call(filter.call(map.call(itThis, getMapResult(m, keyA, resolver)), utils_1.identity)));
};
}
function combineRecipe(combineFuncs) {
const { flatten, map } = combineFuncs;
const innerJoin = getInnerJoin(combineFuncs);
const combineNN = getCombineNN(map, flatten);
return function (iterable, baseKeyA, baseKeyB) {
if (!baseKeyA === !!baseKeyB) {
throw new Error('Both key mapper must be informed, or no one');
}
return baseKeyA
? innerJoin(this, iterable, baseKeyA, baseKeyB)
: combineNN(this, iterable);
};
}