Как убрать стоп-слова из вектора предложений? - PullRequest
0 голосов
/ 10 мая 2019

Я работаю над кодом, который требует удаления стоп-слов из предложений.Мое текущее решение не работает.

У меня есть вектор из двух тестовых предложений:
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);
        }
}

1 Ответ

0 голосов
/ 10 мая 2019

Ваш текущий код не может работать, так как вы не удаляете слова из каждой отдельной строки. Ваш 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 для удаления скрученной вручную петли в приведенном выше примере:

#include <algorithm>
//...
int main()
{
  std::vector<std::string> test = {"this is a test", "another a test"};
  std::unordered_set<std::string> stops = {"is", "test"};

  // Use std::transform
  std::transform(test.begin(), test.end(), test.begin(), 
                 [&](const std::string& s){return remove_stop_words(s, stops);});

  std::cout << "Changed words:\n";
  for ( auto& s : test )
    std::cout << s << "\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...