Skip to content

Instantly share code, notes, and snippets.

@acwhittam
Last active November 3, 2020 14:05
Show Gist options
  • Save acwhittam/52741d55d1ac1fd1846e36a20eec81c5 to your computer and use it in GitHub Desktop.
Save acwhittam/52741d55d1ac1fd1846e36a20eec81c5 to your computer and use it in GitHub Desktop.
let counter = 1;
const db = [];
const entityIndex = new Map();
const valueIndex = new Map();
const attributeIndex = new Map();
const add = (obj) => {
const op = true;
const tx = new Date().getTime();
const entity = counter++;
entityIndex.set(entity, new Set());
const keys = Object.keys(obj);
let idx = 0;
while (idx < keys.length) {
const attribute = keys[idx];
const value = obj[attribute];
if (value) {
const row = [entity, attribute, value, tx, op];
const length = db.push(row);
const dbLocation = length - 1;
entityIndex.get(entity).add(dbLocation);
if (!attributeIndex.has(attribute)) {
attributeIndex.set(attribute, new Set());
}
if (!valueIndex.has(value)) {
valueIndex.set(value, new Set());
}
entityIndex.get(entity).add(dbLocation);
attributeIndex.get(attribute).add(dbLocation);
valueIndex.get(value).add(dbLocation);
}
idx++;
}
};
const isVar = RegExp(/^\?/);
const isWildcard = RegExp(/^_$/);
const intersection = (a, b) => new Set([...a].filter((x) => b.has(x)));
const setToRows = (set) => [...set].map((idx) => db[idx]);
const isSubset = (a, b) => [...a].filter((x) => b.has(x)) === 0;
const merge = (a) => (b) => new Map([...a, ...b]);
const joinable = (keys) => (a) => (b) =>
[...keys].every((key) => a.get(key) === b.get(key));
const applyRule = (rule) => {
const [e, a, v] = rule;
const map = rule.reduce(
(acc, value, index) => (isVar.test(value) ? acc.set(index, value) : acc),
new Map()
);
const sets = [];
if (!isVar.test(e) && !isWildcard.test(e)) {
sets.push(entityIndex.get(e) || new Set());
}
if (!isVar.test(a) && !isWildcard.test(a)) {
sets.push(attributeIndex.get(a) || new Set());
}
if (!isVar.test(v) && !isWildcard.test(v)) {
sets.push(valueIndex.get(v) || new Set());
}
const rows = setToRows(sets.reduce(intersection)).map((row) => {
return [...map].reduce((match, [key, value]) => {
return match.set(value, row[key]);
}, new Map());
});
const vars = new Set(rule.filter((x) => isVar.test(x)));
return { rows, vars };
};
const join = (a, b) => {
const keys = intersection(a.vars, b.vars);
const match = keys.size > 0 ? joinable(keys) : () => () => true;
const vars = new Set([...a.vars, ...b.vars]);
const rows = a.rows.flatMap((row) => {
return b.rows.filter(match(row)).map(merge(row));
});
return { vars, rows };
};
const data = [
{
shelf: "javascript",
isbn: "9781449331818",
},
{
isbn: "9781449325862",
shelf: "git",
},
{
shelf: "javascript",
isbn: "9781593275846",
},
{
isbn: "9781593275846",
title: "Eloquent JavaScript, Second Edition",
subtitle: "A Modern Introduction to Programming",
author: "Marijn Haverbeke",
published: "2014-12-14T00:00:00.000Z",
publisher: "No Starch Press",
pages: 472,
},
{
isbn: "9781449331818",
title: "Learning JavaScript Design Patterns",
subtitle: "A JavaScript and jQuery Developer's Guide",
author: "Addy Osmani",
published: "2012-07-01T00:00:00.000Z",
publisher: "O'Reilly Media",
pages: 254,
},
{
isbn: "9781449365035",
title: "Speaking JavaScript",
subtitle: "An In-Depth Guide for Programmers",
author: "Axel Rauschmayer",
published: "2014-02-01T00:00:00.000Z",
publisher: "O'Reilly Media",
pages: 460,
},
{
isbn: "9781491950296",
title: "Programming JavaScript Applications",
subtitle:
"Robust Web Architecture with Node, HTML5, and Modern JS Libraries",
author: "Eric Elliott",
published: "2014-07-01T00:00:00.000Z",
publisher: "O'Reilly Media",
pages: 254,
},
{
isbn: "9781593277574",
title: "Understanding ECMAScript 6",
subtitle: "The Definitive Guide for JavaScript Developers",
author: "Nicholas C. Zakas",
published: "2016-09-03T00:00:00.000Z",
publisher: "No Starch Press",
pages: 352,
},
{
isbn: "9781491904244",
title: "You Don't Know JS",
subtitle: "ES6 & Beyond",
author: "Kyle Simpson",
published: "2015-12-27T00:00:00.000Z",
publisher: "O'Reilly Media",
pages: 278,
},
{
isbn: "9781449325862",
title: "Git Pocket Guide",
subtitle: "A Working Introduction",
author: "Richard E. Silverman",
published: "2013-08-02T00:00:00.000Z",
publisher: "O'Reilly Media",
pages: 234,
},
{
isbn: "9781449337711",
title: "Designing Evolvable Web APIs with ASP.NET",
subtitle: "Harnessing the Power of the Web",
author: "Glenn Block, et al.",
published: "2014-04-07T00:00:00.000Z",
publisher: "O'Reilly Media",
pages: 538,
},
];
data.forEach(add);
const rules = [
["?book", "publisher", "O'Reilly Media"],
["?book", "author", "?author"],
["?book", "isbn", "?isbn"],
["?shelf", "shelf", "git"],
["?shelf", "isbn", "?isbn"]
];
rules.map(applyRule).reduce(join);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment