合并多对一的对象列表

Merge many-to-one list of objects

本文关键字:列表 对象 多对一 合并      更新时间:2023-09-26

我目前有两个数据库表,代表多对一关系。具有 ID(整数、自动增量、主键)和名称(varchar(255),而不是 null)的活动;和 ActivitySlugs,它们有一个 ID(与上面相同)、一个 slugname(不是空 varchar)和一个activity_id(外键到 Activities.id)。

目前,我应该获取所有活动及其所有 slug 的列表(作为一个列表),因此它看起来像这样:

[
    {id: 1, name: "long name", slugs: ["nick", "names"]},
    {id: 2, name: "foobar", slugs: ["foo", "bar"]}
]

天真的解决方案(也是我能想到的唯一解决方案)是对每个表执行"SELECT *",然后合并它们,但随后我得到的数据如下所示:

activities = [
    {id: 1, name: "long name"},
    {id: 2, name: "foobar"}
]
slugs = [
    {id: 1, slugname: "nick", activity_id: 1},
    {id: 2, slugname: "names", activity_id: 1},
    {id: 3, slugname: "foo", activity_id: 2},
    {id: 4, slugname: "bar", activity_id: 2}
]

因此,我可以遍历两者并添加它们:

activities.forEach(function(activity) {
    slugs = [];
    activitySlugs.forEach(function(slug) {
        if (slug.activity_id == activity.id) {
            slugs.push(slug.name);
        }
    });
    activity.slugs = slugs;
);

这感觉笨拙、缓慢且不精致。它肯定根本不会扩展。不幸的是,我似乎找不到更好的方法来让它们与这样的数组合并为多对一。

您可以构造一个 id2activity 映射,以通过其 id 访问任何活动:

var id2activity = {};
activities.forEach(function(activity) {
    activity.slugs = [];
    id2activity[activity.id] = activity;
);
activitySlugs.forEach(function(slug) {
    id2activity[slug.activity_id].slugs.push(slug.name);
});

由于一个 slug 只能属于一个活动,因此您应该迭代 slug 并附加到某个活动对象。

var activities = [
    {id: 1, name: "long name"},
    {id: 2, name: "foobar"}
];
var slugs = [
    {id: 1, slugname: "nick", activity_id: 1},
    {id: 2, slugname: "names", activity_id: 1},
    {id: 3, slugname: "foo", activity_id: 2},
    {id: 4, slugname: "bar", activity_id: 2}
];
slugs.forEach(function(slug) {
    var a = activities.filter(function(a){return a.id==slug.activity_id;}); 
    // should check if it exists - assume that it does
    if (a[0].slugs == undefined) {
      a[0].slugs = [slug.id];
    } else {
      a[0].slugs.push(slug.id);
    }
});