assignment vs std::swap and merging and keeping duplicates in seperate object
Say I have two std::set<std::string>
s. The first one, old_options
, needs to be merged with additional options, contained in new_options
. I can't just use std::merge
(well, I do, but not only that) because I also check for doubles and warn the user about this accordingly. To this effect, I have
void merge_options( set<string> &old_options, const set<string> &new_options )
{
// find duplicates and create merged_options, a stringset containing the merged options
// handle duplicated the way I want to
// ...
old_options = merged_options;
}
Is it better to use
std::swap( merged_options, old_options );
or the assignment I have?
Is there a better way to filter duplicates and return the merged
se开发者_运维知识库t
than consecutive calls tostd::set_intersection
andstd::set_union
to detect dupes and merge theset
s? I know it's slower than one traversal and doing both at once, but these sets are small (performance is not critical) and I trust the Standard more than I trust myself.
What's wrong with
void merge_options( set<string> &old_options, const set<string> &new_options )
{
for (set<string>::iterator i = new_options.begin();
i != new_options.end(); ++i)
if (old_options.find(*i) != old_options.end())
warn_duplicate(*i);
else
old_options.insert(*i);
}
This is a simple O(m lg n) algorithm, where m = new_options.size()
and n = old_options.size()
.
Given (as you've stated) that performance isn't critical here, I'd use the assignment and the two-pass algorithm. It's simpler and easier to understand; it's only worth using a "trick" like swap if you really need what it gains.
Writing your own algorithm wouldn't be such a bad thing, but again, unless you have a real use for the benefit it provides, I wouldn't bother.
This is in part an answer to larsmans. There is a remove_copy_if
algorithm that encapsulates his for
loop into a single function. The following uses a C++0x lambda for the predicate.
void merge_options( set<string> &old_options, const set<string> &new_options )
{
remove_copy_if(
new_options.begin(),
new_options.end(),
inserter(old_options, old_options.end()),
[&](const string &s) {
return (old_options.count(s)) ? warn_duplicate(s), true : false;
}
);
}
精彩评论