Reputation: 18603
I have a std::multimap< int, std::string >
like that:
1 A
1 B
1 C
1 B
1 C
1 C
and I would like to get a collection of mapped_type
elements with no duplicates, like that:
1 A
1 B
1 C
My solution is like this:
#include <map>
#include <list>
#include <string>
#include <algorithm>
int main(int argc, char* argv[])
{
std::multimap< int, std::string > mm;
mm.insert( std::make_pair(1,"A") );
mm.insert( std::make_pair(1,"B") );
mm.insert( std::make_pair(1,"C") );
mm.insert( std::make_pair(1,"B") );
mm.insert( std::make_pair(1,"C") );
mm.insert( std::make_pair(1,"C") );
auto range( mm.equal_range(1) );
std::list< std::string > ss;
std::transform(range.first, range.second,
std::back_inserter(ss),
[](const std::pair<int,std::string>& p) {
return p.second;
});
ss.sort();
ss.unique();
return 0;
}
Is there any more efficient way to get the collection?
Upvotes: 2
Views: 156
Reputation: 15997
Algorithmically, this is already the most efficient way. Bulk operations like sort and unique almost always trump online operations like set-inserts by constant factors.
That said, it is usually recommended to stay away from node-based containers like list, map and set when performance is key. You could switch to std::vector
, std::sort
and std::unique
, but in your example, that might not be faster, since moving around strings might actually be slower than rearranging list-nodes. If you have move-support and no small-string optimizations active, if might be worth a try.
Upvotes: 2
Reputation: 110658
You can use a std::set
, which only allows unique values, instead of a std::list
:
std::set<std::string> ss;
std::transform(range.first, range.second,
std::inserter(ss, ss.begin()),
[](const std::pair<int,std::string>& p) {
return p.second;
});
Now you don't have to use sort
or unique
.
Upvotes: 2