【问题标题】:Intersection between various values from boost::bimapboost::bimap 中各种值之间的交集
【发布时间】:2014-03-06 05:45:09
【问题描述】:

我正在尝试使用 boost::bimap 来满足我的一项要求。下面是示例代码

typedef bimap<
        multiset_of< string >,
        multiset_of< string >,
        set_of_relation<>
        > bm_type;

 bm_type bm;

 assign::insert( bm )

 ( "John" , string("lazarus" ) )
 ( "Peter", string("vinicius") )
 ( "Peter", string("test") )
 ( "Simon", string("vinicius") )
 ( "John", string("viniciusa") )
 ( "John", string("vinicius") )

我想做一些事情,比如为 John 和 Peter 找到匹配值,换句话说,就是 John 和 Peter 的值之间的交集,例如:在这种情况下,它将是 ("vinicius")。有人可以提供一些关注吗?

【问题讨论】:

    标签: c++ boost boost-bimap


    【解决方案1】:

    这是我最初想出的:

    template <typename Value = std::string, typename Bimap, typename Key>
    std::set<Value> projection(Bimap const& bm, Key const& key)
    {
        std::set<Value> p;
        auto range  = bm.left.equal_range(key);
        auto values = boost::make_iterator_range(range.first, range.second);
    
        for (auto& relation : values)
            p.insert(relation.template get<boost::bimaps::member_at::right>());
    
        return p;
    }
    
    auto john  = projection(bm, "John");
    auto peter = projection(bm, "Peter");
    
    std::multiset<std::string> intersection;
    std::set_intersection(
             john.begin(), john.end(),
             peter.begin(), peter.end(),
             inserter(intersection, intersection.end())
         );
    

    我认为它可以更有效。所以我尝试使用 Boost Range 的适配器动态替换投影:

    struct GetRightMember
    {
        template <typename> struct result { typedef std::string type; };
    
        template <typename T>
        std::string operator()(T const& v) const {
            return v.template get<boost::bimaps::member_at::right>();
        }
    };
    
    const GetRightMember getright;
    std::cout << "Intersection: ";
    
    // WARNING: broken: ranges not sorted
    boost::set_intersection(
            bm.left.equal_range("John")  | transformed(getright),
            bm.left.equal_range("Peter") | transformed(getright),
            std::ostream_iterator<std::string>(std::cout, " "));
    

    遗憾的是它不起作用 - 大概是因为转换后的范围没有排序。

    所以我会坚持使用更详细的版本(或重新考虑我的数据结构选择)。看到它Live On Coliru

    【讨论】:

    • 如果我使用 unordered_multiset_of 的 bimap ,同样的方法也会起作用?
    • 我强烈期待这一点。你有没有尝试过? 更新 59 秒后:coliru.stacked-crooked.com/a/69e331d13cef1c65
    • 我可以通过 unordered_map (key 2 set of values) & another unordered_map > (value to 2 unordered_set of keys)来实现我的用例.在那种情况下,我需要管理从第一个地图中删除,如果在第二个和反之亦然被删除(当然对于添加也是相同的),但这样我就不需要创建集合来查找不同键之间的交集,你呢?认为这会比使用 bimap 更有效?
    • 我使用了vector,可能这样会更有效率。有什么建议? coliru.stacked-crooked.com/a/11c7df52bfbae15f
    • @Peetish 我希望矢量版本更快,至少对于较小的右手子集。证明当然在分析中。我相信你能做到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多