Reputation: 14374
I have two objects that represent two SQL tables. Here are two simplified versions (they both might have many more properties):
const object1 = {
key1: [ 1, 1, 1, 2, 2, 3 ],
key2: ['a', 'b', 'c', 'a', 'c', 'b'],
prop3: ['A', 'B', 'C', 'D', 'E', 'F'],
}
const object2 = {
key1: [ 1, 1, 2],
key2: ['a', 'c', 'a'],
prop4: [10, 20, 30],
}
I would like to perform a left-join on key1
and key2
. Something like:
select *
from object1 o1
left join object2 o2 on o1.key1 = o2.key1 and o1.key2 = o2.key2
Or in JS:
const object12 = {
key1: [ 1, 1, 1, 2, 2, 3 ],
key2: ['a', 'b', 'c', 'a', 'c', 'b'],
prop3: ['A', 'B', 'C', 'D', 'E', 'F'],
prop4: [10, null, 20, 30, null, null],
}
What's a convenient way to do this in JS? (using lodash is allowed)
Upvotes: 0
Views: 82
Reputation: 138277
const table = (entries, keys) => {
const toData = () => Object.fromEntries(keys.map(k => [k, entries.map(it => it[k] ?? null)]));
const join = (other, on) => table(
entries.map(entry => ({ ...entry, ...(other.entries.find(other => on(entry, other)) ?? {}) })),
[...keys, ...other.keys]
);
return { entries, keys, join, toData };
};
table.from = data => {
const keys = Object.keys(data);
const entries = [];
for(let i = 0; i < data[keys[0]].length; i++) {
const entry = entries[i] = {};
for(const key of keys)
entry[key] = data[key][i];
}
return table(entries, keys);
};
In action:
const table = (entries, keys) => {
const toData = () => Object.fromEntries(keys.map(k => [k, entries.map(it => it[k] ?? null)]));
const join = (other, on) => table(
entries.map(entry => ({ ...entry, ...(other.entries.find(other => on(entry, other)) ?? {}) })),
[...keys, ...other.keys]
);
return { entries, keys, join, toData };
};
table.from = data => {
const keys = Object.keys(data);
const entries = [];
for(let i = 0; i < data[keys[0]].length; i++) {
const entry = entries[i] = {};
for(const key of keys)
entry[key] = data[key][i];
}
return table(entries, keys);
};
const object1 = { key1: [ 1, 1, 1, 2, 2, 3 ], key2: ['a', 'b', 'c', 'a', 'c', 'b'], prop3: ['A', 'B', 'C', 'D', 'E', 'F'] };
const object2 = { key1: [ 1, 1, 2], key2: ['a', 'c', 'a'], prop4: [10, 20, 30] };
const result = table.from(object1)
.join(table.from(object2), (a, b) => a.key1 === b.key1 && a.key2 === b.key2)
.toData();
console.log(result);
Upvotes: 1