I think what you want is an inner join , which is simple enough to implement in JavaScript:
(我认为您想要的是一个内部联接 ,它很简单,可以在JavaScript中实现:)
const innerJoin = (xs, ys, sel) =>
xs.reduce((zs, x) =>
ys.reduce((zs, y) => // cartesian product - all combinations
zs.concat(sel(x, y) || []), // filter out the rows and columns you want
zs), []);
For the purpose of demonstration we'll use the following data set (thank you @AshokDamani):
(出于演示目的,我们将使用以下数据集(感谢@AshokDamani):)
const userProfiles = [
{id: 1, name: "Ashok"},
{id: 2, name: "Amit"},
{id: 3, name: "Rajeev"},
];
const questions = [
{id: 1, text: "text1", createdBy: 2},
{id: 2, text: "text2", createdBy: 2},
{id: 3, text: "text3", createdBy: 1},
{id: 4, text: "text4", createdBy: 2},
{id: 5, text: "text5", createdBy: 3},
{id: 6, text: "text6", createdBy: 3},
];
This is how you would use it:
(这是您将如何使用它:)
const result = innerJoin(userProfiles, questions,
({id: uid, name}, {id, text, createdBy}) =>
createdBy === uid && {id, text, name});
In SQL terms this would be similar to:
(用SQL术语,这类似于:)
SELECT questions.id, questions.text, userProfiles.name
FROM userProfiles INNER JOIN questions
ON questions.createdBy = userProfiles.id;
Putting it all together:
(放在一起:)
const innerJoin = (xs, ys, sel) => xs.reduce((zs, x) => ys.reduce((zs, y) => // cartesian product - all combinations zs.concat(sel(x, y) || []), // filter out the rows and columns you want zs), []); const userProfiles = [ {id: 1, name: "Ashok"}, {id: 2, name: "Amit"}, {id: 3, name: "Rajeev"}, ]; const questions = [ {id: 1, text: "text1", createdBy: 2}, {id: 2, text: "text2", createdBy: 2}, {id: 3, text: "text3", createdBy: 1}, {id: 4, text: "text4", createdBy: 2}, {id: 5, text: "text5", createdBy: 3}, {id: 6, text: "text6", createdBy: 3}, ]; const result = innerJoin(userProfiles, questions, ({id: uid, name}, {id, text, createdBy}) => createdBy === uid && {id, text, name}); console.log("Open your browser console to see the output."); console.table(result);
Edit: However this is not the best solution.
(编辑:但是,这不是最好的解决方案。)
Since the above solution loops through the Cartesian product it takes O(m × n)
time to run.(由于上述解决方案遍历笛卡尔积,因此需要O(m × n)
时间来运行。)
With a little bit of modification we can make it run in O(m + n)
time - @pebbl found it first :(进行一些修改,我们可以使其在O(m + n)
时间内运行-@pebbl首先找到它 :)
const equijoin = (xs, ys, primary, foreign, sel) => {
const ix = xs.reduce((ix, row) => // loop through m items
ix.set(row[primary], row), // populate index for primary table
new Map); // create an index for primary table
return ys.map(row => // loop through n items
sel(ix.get(row[foreign]), // get corresponding row from primary
row)); // select only the columns you need
};
Now you could use it as follows:
(现在您可以按以下方式使用它:)
const result = equijoin(userProfiles, questions, "id", "createdBy",
({name}, {id, text}) => ({id, text, name}));
Putting it all together:
(放在一起:)
const equijoin = (xs, ys, primary, foreign, sel) => { const ix = xs.reduce((ix, row) => ix.set(row[primary], row), new Map); return ys.map(row => sel(ix.get(row[foreign]), row)); }; const userProfiles = [ {id: 1, name: "Ashok"}, {id: 2, name: "Amit"}, {id: 3, name: "Rajeev"}, ]; const questions = [ {id: 1, text: "text1", createdBy: 2}, {id: 2, text: "text2", createdBy: 2}, {id: 3, text: "text3", createdBy: 1}, {id: 4, text: "text4", createdBy: 2}, {id: 5, text: "text5", createdBy: 3}, {id: 6, text: "text6", createdBy: 3}, ]; const result = equijoin(userProfiles, questions, "id", "createdBy", ({name}, {id, text}) => ({id, text, name})); console.log("Open your browser console to see the output."); console.table(result);