【问题标题】:Algorithm: Selecting common elements of a collection算法:选择集合的共同元素
【发布时间】:2010-12-02 19:56:48
【问题描述】:

我最近不得不写以下算法:

给定一组标签,以及一组 博客文章,其中博客文章可能 包含零对多标签,返回 所有帖子共有的标签。

此比较是在内存中完成的 - 访问任一集合不会导致跨网络(即,访问数据库等)。

此外,Tags 集合没有对包含它的 BlogPosts 的引用。 BlogPosts 有一组 Tags 它们包含。

以下是我的实现。它执行得很好,但我很好奇是否有更好的方法来实现它。

我的实现是在 Actionscript 中,但从算法的角度来看,我更好奇,所以任何语言的示例都可以。 (但如果我不懂语言,我可能会要求你澄清一些方面)

任何改进的例子都会受到极大的欢迎。

    private function getCommonTags(blogPosts:Vector.<BlogPost>):Vector.<Tag>
    {
        var commonTags:Vector.<Tag> = new Vector.<Tag>();
        if (!blogPosts || blogPosts.length == 0)
            return commonTags;

        var blogPost:BlogPost = blogPosts[0];
        if (!blogPost.tags || blogPost.tags.length == 0)
            return commonTags;

        commonTags = Vector.<Tag>(blogPosts[0].tags);

        for each (var blogPost:BlogPost in blogPosts)
        {
            if (!blogPost.tags || blogPost.tags.length == 0 || commonTags.length == 0)
                // Updated to fix bug mentioned below
                // Optomized exit - there are no common tags
                return new Vector.<Tag>();

            for each (var tag:Tag in commonTags)
            {
                if (!blogPost.containsTagId(tag.id))
                {
                    commonTags.splice(commonTags.indexOf(tag),1);
                }
            }
        }
        return commonTags;
    }

【问题讨论】:

  • 我不知道 Actionscript,但是如果您可以通过 blogPost.tags.length 廉价地订购 blogposts,这段代码会运行得更快。另外我认为当第一篇文章有​​ 2 个标签而第二个 0 时存在错误,它将返回第一篇文章的 2 个标签。
  • @krusty.ar 谢谢!按标签数量排序是个好主意。我认为您提到的错误是由于我代表我重命名了一些糟糕的变量 - 我已经编辑了代码,如果您仍然看到错误,请告诉我(我没有)。
  • 好吧,假设 blogPosts[0].tags.lenght == 2 和 blogPosts[0].tags.lenght == 0,for each 循环的第一遍会比较两个标签第一篇文章有​​第一篇文章的 2 个标签,它们是相同的,所以 commonTags.lenght == 2,在循环的第二遍中,blogPost.tags.length == 0,所以使用“优化退出”,但是仍然是 commonTags.lenght == 2,所以您要返回第一篇文章的标签,而第二篇文章没有,正确的版本将类似于 return new Vector.();
  • 你是绝对正确的。谢谢 - 我会解决的。

标签: algorithm performance language-agnostic


【解决方案1】:

嗯,你只需要一个高效的算法来计算两个集合的交集,因为你可以重复调用两个以上集合的算法。

一种快速算法是将第一个集合的项目添加到哈希表中,然后遍历第二个集合,检查哈希表是否存在;如果是,则将其添加到要在交集中返回的项目列表中。

【讨论】:

    【解决方案2】:

    我可以用一个英文句子来说明这个程序:“返回所有在帖子中统一出现的标签。”

    给标签列表命名all_tags,给标签关联到帖子列表命名post_tags,我可以用J programming language中的这句话说同样的话

       all_tags #~ (#=+/) all_tags e.&>"_ 0 post_tags
    

    详细了解一下:

    • #~ 表示“复制到哪里”

    • (# = +/) 表示“计数等于总和”

    • e. 表示“存在于”

    • &amp;&gt;"_ 0 修改了e.,因此将整个all_tagspost_tags 中的每个标签集进行比较

    如果我们想让它成为一个接受两个参数的程序,而不是一个特定于这些命名列表的程序,相应的程序可以是:

       common_to=:  [ #~ [:(#=+/) [ e.&>"_ 0 ]
    

    使用相同的数据名称运行该程序将如下所示:

       all_tags common_to post_tags
    

    值得注意的是,我们实际上并不需要完整的标签列表,因为它可以推导出来。 (计算是~. ; post_tags。)这意味着我们可以编写程序来只接受一个参数。但由于问题假定我们已经计算了all_tags 列表,因此无需再次计算。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      相关资源
      最近更新 更多