开发者

assignment vs std::swap and merging and keeping duplicates in seperate object

开发者 https://www.devze.com 2023-02-15 07:13 出处:网络
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 th

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;
}
  1. Is it better to use

    std::swap( merged_options, old_options );
    

    or the assignment I have?

  2. Is there a better way to filter duplicates and return the merged se开发者_运维知识库t than consecutive calls to std::set_intersection and std::set_union to detect dupes and merge the sets? 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;
        }
    );
}
0

精彩评论

暂无评论...
验证码 换一张
取 消