Advertisement
Petrovi4

SplitIntoSentences

Aug 8th, 2022 (edited)
847
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.30 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cassert>
  3. #include <string>
  4. #include <vector>
  5. #include <iostream>
  6.  
  7. //
  8.  
  9.  
  10.  
  11. // Объявляем Sentence<Token> для произвольного типа Token
  12. // синонимом vector<Token>.
  13. // Благодаря этому в качестве возвращаемого значения
  14. // функции можно указать не малопонятный вектор векторов,
  15. // а вектор предложений — vector<Sentence<Token>>.
  16. template <typename Token>
  17. using Sentence = std::vector<Token>;
  18.  
  19. template <typename TokenForwardIt>
  20. TokenForwardIt FindSentenceEnd(TokenForwardIt tokens_begin, TokenForwardIt tokens_end) {
  21.     const TokenForwardIt before_sentence_end
  22.         = std::adjacent_find(tokens_begin, tokens_end, [](const auto& left_token, const auto& right_token) {
  23.         return left_token.IsEndSentencePunctuation() && !right_token.IsEndSentencePunctuation();
  24.             });
  25.     return before_sentence_end == tokens_end ? tokens_end : next(before_sentence_end);
  26. }
  27.  
  28. // Класс Token имеет метод bool IsEndSentencePunctuation() const
  29. template <typename Token>
  30. std::vector<Sentence<Token>> SplitIntoSentences(std::vector<Token> tokens) {
  31.     std::vector<std::vector<Token>> result;
  32.     auto it_start = tokens.begin();
  33.     while (it_start != tokens.end()) {
  34.         auto it_end_sentence = FindSentenceEnd(it_start, tokens.end());
  35.         std::vector<Token> tmp;
  36.         for (auto it_begin = it_start; it_begin != it_end_sentence; ++it_begin) {
  37.             tmp.push_back(std::move(*it_begin));
  38.         }
  39.         result.push_back(std::move(tmp));
  40.  
  41.         it_start = (it_end_sentence);
  42.     }
  43.     return result;
  44. }
  45.  
  46. struct TestToken {
  47.     std::string data;
  48.     bool is_end_sentence_punctuation = false;
  49.  
  50.     bool IsEndSentencePunctuation() const {
  51.         return is_end_sentence_punctuation;
  52.     }
  53.     bool operator==(const TestToken& other) const {
  54.         return data == other.data && is_end_sentence_punctuation == other.is_end_sentence_punctuation;
  55.     }
  56. };
  57.  
  58. std::ostream& operator<<(std::ostream& stream, const TestToken& token) {
  59.     return stream << token.data;
  60. }
  61.  
  62. // Тест содержит копирования объектов класса TestToken.
  63. // Для проверки отсутствия копирований в функции SplitIntoSentences
  64. // необходимо написать отдельный тест.
  65. void TestSplitting() {
  66.     using namespace std;
  67.     assert(SplitIntoSentences(vector<TestToken>({ {"Split"s}, {"into"s}, {"sentences"s}, {"!"s} }))
  68.         == vector<Sentence<TestToken>>({ {{"Split"s}, {"into"s}, {"sentences"s}, {"!"s}} }));
  69.  
  70.     assert(SplitIntoSentences(vector<TestToken>({ {"Split"s}, {"into"s}, {"sentences"s}, {"!"s, true} }))
  71.         == vector<Sentence<TestToken>>({ {{"Split"s}, {"into"s}, {"sentences"s}, {"!"s, true}} }));
  72.  
  73.     assert(SplitIntoSentences(vector<TestToken>(
  74.         { {"Split"s}, {"into"s}, {"sentences"s}, {"!"s, true}, {"!"s, true}, {"Without"s}, {"copies"s}, {"."s, true} }))
  75.         == vector<Sentence<TestToken>>({
  76.             {{"Split"s}, {"into"s}, {"sentences"s}, {"!"s, true}, {"!"s, true}},
  77.             {{"Without"s}, {"copies"s}, {"."s, true}},
  78.             }));
  79. }
  80.  
  81. int main() {
  82.     TestSplitting();
  83.     return 0;
  84. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement