C++ 赋值vs std::交换、合并并在单独的对象中保留重复项
假设我有两个C++ 赋值vs std::交换、合并并在单独的对象中保留重复项,c++,algorithm,merge,set,C++,Algorithm,Merge,Set,假设我有两个std::sets。第一个选项,old\u options,需要与包含在new\u options中的其他选项合并。我不能只使用std::merge(当然,我可以,但不仅如此),因为我还检查double并相应地警告用户。为此,我有 void merge_options( set<string> &old_options, const set<string> &new_options ) { // find duplicates and
std::set
s。第一个选项,old\u options
,需要与包含在new\u options
中的其他选项合并。我不能只使用std::merge
(当然,我可以,但不仅如此),因为我还检查double并相应地警告用户。为此,我有
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;
}
还是我的任务
std::set_intersection
和std::set_union
更好的方法来过滤重复项并返回合并的set
,以检测重复项并合并set
s?我知道这比一次遍历和同时执行两次遍历要慢,但这些集合很小(性能并不重要),我更信任标准,而不是我自己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);
}
无效合并选项(设置和旧选项、常量设置和新选项)
{
for(set::iterator i=new_options.begin();
i!=新的_选项.end();++i)
if(old_options.find(*i)!=old_options.end())
警告重复(*i);
其他的
旧选项。插入(*i);
}
这是一个简单的O(mlgn)算法,其中m=
新选项.size()
和n=旧选项.size()
这部分是对拉斯曼的回答。有一个remove\u copy\u if
算法将他的for
循环封装到一个函数中。下面使用C++0x lambda作为谓词
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;
}
);
}
无效合并选项(设置和旧选项、常量设置和新选项)
{
如果需要,请删除\u复制\u(
新的\u选项。开始(),
新的_选项。结束(),
插入器(旧选项,旧选项.end()),
[&](常量字符串&s){
返回(旧选项计数)?警告重复,真:假;
}
);
}
simple,是的,但在性能上并不相同(如果忽略因子2,这在big-O中应该不重要)。我在脑海中有一个同步遍历,它本质上是O(log(max(m,n)))。这将真正获得性能,但是正如杰瑞所说,这里更复杂,也许没有用处。我只是确保我没有错过C++库函数。@ RuNVB:同时遍历将是O(max(m,n))。,我想。这个版本和你的版本的区别是1)更少的分配和复制(假设C++03),2)我认为我的版本更清晰。我不认为标准库有较短的方法来实现这一点,但我必须承认,
一直让我感到惊讶。啊,是的,log
用于二进制搜索,愚蠢的我=s
@高炉也有一个不错的。(而且
也让我感到惊讶,因此我提出了一个问题)是的,同样复杂。lambda介绍人中的&
是做什么的?我还不熟悉lambda。@larsmans:这是一个capture子句,允许lambda访问封闭范围内的变量。&
通过引用访问所有捕获的变量。在这种情况下,它允许lambda查看(和修改)旧的_选项集。
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;
}
);
}