算法:选择集合的公共元素

时间:2010-12-02 19:56:49

标签: algorithm performance language-agnostic

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

  

给出一组标签和一组标签   博客文章,博客文章可能   包含零对多标签,返回   所有帖子共有的标签。

这种比较是在内存中完成的 - 访问集合导致网络中的旅行(即,到数据库等)。

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

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

我的实现是在Actionscript中,但我对algorithim的观点更加好奇,所以任何语言的例子都很好。 (但如果我不懂语言,我可能会要求你澄清一些方面)

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

    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;
    }

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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

将名称all_tags提供给代码列表,将post_tags提供给与帖子关联的代码列表,我可以在J programming language中对此句话说同样的话

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

详细看一下:

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

  • (# = +/)表示“理货等于总和”

  • e.表示“存在于”

  • &>"_ 0修改e.,以便将all_tags的整体与post_tags

  • 中的每个标记集进行比较

如果我们想让这个程序带有两个参数,而不是一个特定于这些命名列表的程序,那么相应的程序可能是:

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

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

   all_tags common_to post_tags

似乎值得注意的是,我们实际上并不需要全面的标签列表,因为可以派生出来。 (计算结果为~. ; post_tags。)这意味着我们可以编写程序只采用一个参数。但由于问题假设我们已经计算了all_tags列表,因此无需再次计算它。