thi-ng/umbrella

View on GitHub
packages/rstream-query/src/xforms.ts

Summary

Maintainability
A
35 mins
Test Coverage
import type { IObjectOf } from "@thi.ng/api";
import { intersection } from "@thi.ng/associative/intersection";
import { join } from "@thi.ng/associative/join";
import { equiv } from "@thi.ng/equiv";
import { LOGGER } from "@thi.ng/rstream/logger";
import type { Reducer, Transducer } from "@thi.ng/transducers";
import { comp } from "@thi.ng/transducers/comp";
import { compR } from "@thi.ng/transducers/compr";
import { dedupe } from "@thi.ng/transducers/dedupe";
import { keySelector } from "@thi.ng/transducers/key-selector";
import { map } from "@thi.ng/transducers/map";
import type { BindFn, Edit, Solutions, Triple, TripleIds } from "./api.js";
import type { TripleStore } from "./store.js";

export const intersect2: Transducer<IObjectOf<TripleIds>, TripleIds> = comp(
    map(({ a, b }) => intersection(a, b)),
    dedupe(equiv)
);

export const intersect3: Transducer<IObjectOf<TripleIds>, TripleIds> = comp(
    map(({ s, p, o }) => intersection(intersection(s, p), o)),
    dedupe(equiv)
);

export const indexSel =
    (key: any): Transducer<Edit, TripleIds> =>
    (rfn: Reducer<TripleIds, any>) => {
        const r = rfn[2];
        return compR(rfn, (acc, e) => {
            LOGGER.fine("index sel", e.key, key);
            return equiv(e.key, key) ? r(acc, e.index) : acc;
        });
    };

export const resultTriples = (graph: TripleStore) =>
    map<TripleIds, Set<Triple>>((ids) => {
        const res = new Set<Triple>();
        for (let id of ids) res.add(graph.triples[id]);
        return res;
    });

export const joinSolutions = (n: number) =>
    map<IObjectOf<Solutions>, Solutions>((src) => {
        let res: Solutions = src[0];
        for (let i = 1; i < n && res.size; i++) {
            res = join(res, src[i]);
        }
        return res;
    });

export const filterSolutions = (qvars: Iterable<string>) => {
    const filterVars = keySelector([...qvars]);
    return map((sol: Solutions) => {
        const res: Solutions = new Set();
        for (let s of sol) {
            res.add(filterVars(s));
        }
        return res;
    });
};

export const limitSolutions = (n: number) =>
    map((sol: Solutions) => {
        if (sol.size <= n) {
            return sol;
        }
        const res: Solutions = new Set();
        let m = n;
        for (let s of sol) {
            res.add(s);
            if (--m <= 0) break;
        }
        return res;
    });

export const bindVars = (bindings: IObjectOf<BindFn>) =>
    map((sol: Solutions) => {
        const res: Solutions = new Set();
        for (let s of sol) {
            s = { ...s };
            res.add(s);
            for (let b in bindings) {
                s[b] = bindings[b](s);
            }
        }
        return res;
    });