我正在处理一些要求从句子中删除停用词的代码。我当前的解决方案不起作用。
我有两个测试句子的向量:
std::vector<std::string> sentences = {"this is a test", "another a test"};
我有一组包含停用词的无序字符串:
std::unordered_set<std::string> stopwords;
现在,我尝试遍历向量中的句子,检查每个单词并将其与停用词进行比较,如果是停用词,则应将其删除。
sentences.erase(std::remove_if(sentences.begin(), sentences.end(),
[](const std::string &s){return stopwords.find(s) != stopwords.end();}),
sentences.end());
这个想法是,我的向量-在删除停用词之后-包含不包含停用词的句子,但是现在,我又得到了完全相同的句子。知道为什么吗?
我的无序集合充满了以下功能:
void load() {
std::ifstream file;
file.open ("stopwords.txt");
if(!file.is_open()) {return;}
std::string stopword;
while (file >> stopword) {
stopwords.insert(stopword);
}
}
答案 0 :(得分:0)
您当前的代码无效,因为您没有从每个字符串中删除单词。您的INT(5)
调用将使用整个字符串,并尝试将集合中的单词与整个字符串匹配。
首先,您应该编写一个简单的函数,当给定erase/remove_if
和要删除的单词映射时,返回包含已删除单词的字符串。
这是一个使用std::string
的小功能,可以做到这一点:
std::istringstream
输出:
#include <unordered_set>
#include <sstream>
#include <string>
#include <iostream>
std::string remove_stop_words(const std::string& src, const std::unordered_set<std::string>& stops)
{
std::string retval;
std::istringstream strm(src);
std::string word;
while (strm >> word)
{
if ( !stops.count(word) )
retval += word + " ";
}
if ( !retval.empty())
retval.pop_back();
return retval;
}
int main()
{
std::string test = "this is a test";
std::unordered_set<std::string> stops = {"is", "test"};
std::cout << "Changed word:\n" << remove_stop_words(test, stops) << "\n";
}
因此,一旦您可以正常使用此功能, Changed word:
this a
版本就是在向量中的每个项目之间循环并调用std::vector
函数:
remove_stop_words
输出:
int main()
{
std::vector<std::string> test = {"this is a test", "another a test"};
std::unordered_set<std::string> stops = {"is", "test"};
for (size_t i = 0; i < test.size(); ++i)
test[i] = remove_stop_words(test[i], stops);
std::cout << "Changed words:\n";
for ( auto& s : test )
std::cout << s << "\n";
}
请注意,在上面的示例中,您可以利用Changed words:
this a
another a
函数来删除手卷循环:
std::transform