我有一个multimap,我想获得一组集合 - 它们将多图中共享相同密钥的所有A类项目组合在一起。在STL中是否有内置的方法来执行此操作?
答案 0 :(得分:2)
我认为没有内置方式。但是手动操作很容易:
std::multimap<key, value> mm;
// ...
std::multimap<key, value>::const_iterator i = mm.begin();
while (i != mm.end())
{
std::multimap<key, value>::const_iterator end = mm.upper_bound(i->first);
// construct a set from the values in [i, end)
i = end;
}
或类似的东西。
答案 1 :(得分:1)
你可以在一对上使用一套。
首先定义一对。该对需要将键作为第一个元素,将实例作为第二个元素。
E.g。假设我们有一系列书籍,我们希望按作者分组:
typedef std::pair<Author *,Book *> AuthorBookPair;
然后在这一对上定义一个集合:
typedef set<AuthorBookPair> BooksGroupedByAuthor;
可以像这样填充集合:
BooksGroupedByAuthor books;
books.insert (std::make_pair(book1->getAuthor(),book1));
books.insert (std::make_pair(book2->getAuthor(),book2));
books.insert (std::make_pair(book3->getAuthor(),book3));
books.insert (std::make_pair(book4->getAuthor(),book4));
现在,您只需使用lower_bound和upper_bound方法查找作者的书籍:
#define POINTER_SMALLEST 0x00000000
#define POINTER_LARGEST 0xffffffff
BooksGroupedByAuthor::const_iterator lowerbound = books.lower_bound(std::make_pair(myFavoriteAuthor,POINTER_POINTER));
BooksGroupedByAuthor::const_iterator upperbound = books.upper_bound(std::make_pair(myFavoriteAuthor,POINTER_POINTER));
现在只需在lowerbound和upperbound之间进行迭代,即可获得该作者的所有书籍。
这个技巧依赖于我选择存储指向书籍的事实,并且我知道最小和最大的指针是什么(对于64位应用程序,您将不得不更改它!)。我必须承认这不是最好的伎俩。
稍微好一点的替代方法是自己存储书籍(如果你的应用程序允许复制这些实例)并制作2个特定的Book实例,分别代表“最小书”和“最大书”
关于这个技巧的好处是它允许在需要时添加更多尺寸。例如。您可以将年份添加为第二维,然后选择仅查找作者的书籍,或者查找特定年份的作者的书籍。使用更多维度时,新C ++ 0x中的元组可能会变得很方便。
这个技巧还有一个优点,就是它可以防止你两次添加一本书。如果一本书被添加两次,它仍然会在集合中一次(如果我们假设书的作者永远不会改变)。如果你要使用multi_map,你可以两次添加同一本书,这可能是不想要的。
答案 2 :(得分:1)
您可以按照以下方式(但使用更合适的名称)执行以下操作。请注意,输出结构实际上是集合的映射而不是一组集合,因为这样就可以保留密钥。
#include <map>
#include <set>
template <class key_t, class value_t>
struct transform_fn {
typedef std::multimap<key_t, value_t> src_t;
typedef std::map<key_t, std::set<value_t> > dest_t;
dest_t operator()(src_t const& src) const
{
dest_t dest;
typedef typename src_t::const_iterator iter_t;
for (iter_t i = src.begin(), e = src.end(); i != e; ++i) {
dest[i->first].insert(i->second);
}
return dest;
}
};
#include <string>
int
main()
{
typedef std::multimap<std::string, int> some_map_t;
typedef std::map<std::string, std::set<int> > tr_some_map_t;
some_map_t src;
transform_fn<std::string, int> tr;
tr_some_map_t dest = tr(src);
return 0;
}
答案 3 :(得分:1)
这会创建一组集合。集合并没有多大意义。
您可以执行以下设置中的每个元素:
our_map[iter->first].insert(iter->second);
如果你有迭代器或
our_map[p.first].insert(p.second);
使用value_type对。
无论哪种方式,如果找不到iter-&gt;,则outer_set上的operator []将创建一个空的内部集合,如果该密钥已经存在,则将检索现有的内部集合。
这样可行,但不是最有效的方法。原因是我们知道p.first要么匹配我们看到的最后一个键,要么必须在最后插入,但上面每次都进行查找。因此,更有效的方法是保持我们的set迭代器。 value_type here是我们的multimap
的值类型BOOST_FOREACH( elt, our_multimap )
{
if( our_map.empty() || elt.key != last_key )
{
last_key = elt.key;
map_iter = our_map.insert(
std::make_pair<elt.key, std::set<value_type>(),
our_map.end() ).first;
}
our_iter->insert( elt.value );
}
注意我们在插入时捕获迭代器,它是std :: map返回的第一个迭代器。
如果您不想使用迭代器,可以使用指向std :: set的指针。
std::set<value_type> *p_set = NULL;
key_type last_key;
BOOST_FOREACH( elt, our_multimap )
{
if( !p_set || elt.key != last_key )
{
last_key = elt.key;
p_set = &our_map[elt.key];
}
p_set->insert( elt.value );
}
这仍然具有在我们点击重复键时不必查找的优点,但是缺点是我们无法将“提示”传递给operator [],就像我们可以插入一样。