我正在使用visual studio 2012(windows),我正在尝试编写一个高效的c ++函数来从一个大的字符串向量中删除一些单词。
我正在使用stl算法。我是一名c ++初学者,所以我不确定这是最好的方法。这就是我所做的:
#include <algorithm>
#include <unordered_set>
using std::vector;
vector<std::string> stripWords(vector<std::string>& input,
std::tr1::unordered_set<std::string>& toRemove){
input.erase(
remove_if(input.begin(), input.end(),
[&toRemove](std::string x) -> bool {
return toRemove.find(x) != toRemove.end();
}));
return input;
}
但是这不起作用,它不会遍历所有输入向量。
这是我如何测试我的代码:
vector<std::string> in_tokens;
in_tokens.push_back("removeme");
in_tokens.push_back("keep");
in_tokens.push_back("removeme1");
in_tokens.push_back("removeme1");
std::tr1::unordered_set<std::string> words;
words.insert("removeme");
words.insert("removeme1");
stripWords(in_tokens,words);
答案 0 :(得分:6)
您需要erase
的双参数形式。不要超越自己并在不同的路线上写下来:
auto it = std::remove_if(input.begin(), input.end(),
[&toRemove](std::string x) -> bool
{ return toRemove.find(x) != toRemove.end(); });
input.erase(it, input.end()); // erases an entire range
答案 1 :(得分:3)
使用std::remove_if()
的方法几乎是正确的方法,但它只删除了一个元素。您需要使用erase()
的两个参数版本:
input.erase(
remove_if(input.begin(), input.end(),
[&toRemove](std::string x) -> bool {
return toRemove.find(x) != toRemove.end();
}), input.end());
std::remove_if()
重新排序元素,使得保留的元素位于序列的前面。它将迭代器it
返回到第一个位置,该位置将被视为序列的新结尾,即,您需要删除范围[it, input.end())
。
答案 2 :(得分:1)
你已经得到了关于如何正确解决这个问题的几个答案。
现在,问题是你是否可以提高效率。答案取决于另一个问题:你关心向量中字符串的顺序吗?
如果您可以重新排列向量中的字符串而不会出现问题,那么您可以使删除效率大大提高。
不是从矢量中间移除字符串(需要移动所有其他字符串以填充孔),而是可以将所有不需要的字符串交换到矢量的末尾,然后将其删除。
特别是如果你只是从大型矢量的开头附近删除一些字符串,这可以提高 lot 的效率。例如,假设您要删除的字符串后跟1000个其他字符串。有了这个,你最终只交换两个字符串,然后擦除最后一个字符串(这很快)。使用当前的方法,最终只移动1000个字符串以删除一个。
更好的是,即使使用相当旧的编译器,您也可以预期交换字符串通常会非常快 - 通常比移动字符串更快(除非您的编译器足够新以支持移动分配)。