Seredenko-V

search_server_cpp_string_view

Aug 5th, 2022 (edited)
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.38 KB | None | 0 0
  1. #include "search_server.h"
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6. SearchServer::SearchServer(const string& stop_words_text)
  7.     : SearchServer(SplitIntoWords(stop_words_text))  // Invoke delegating constructor from string container
  8. {
  9. }
  10.  
  11. SearchServer::SearchServer(const string_view stop_words_text)
  12.     : SearchServer(SplitIntoWords(stop_words_text)) {
  13. }
  14.  
  15. void SearchServer::AddDocument(int document_id, const string_view document, DocumentStatus status,
  16.     const vector<int>& ratings) {
  17.     if (documents_.count(document_id) > 0) {
  18.         throw invalid_argument("Документ с таким id уже существует."s);
  19.     }
  20.     else if (document_id < 0) {
  21.         throw invalid_argument("Документ не может иметь отрицательный id."s);
  22.     }
  23.     else if (!IsValidWord(document)) {
  24.         throw invalid_argument("Содержимое документа содержит недопустимые символы"s);
  25.     }
  26.     const vector<string_view> words = SplitIntoWordsNoStop(document);
  27.     const double inv_word_count = 1.0 / words.size();
  28.     for (const string_view word : words) {
  29.         word_frequencies_in_document_[document_id][string(word)] += inv_word_count;
  30.         word_to_document_freqs_[(word_frequencies_in_document_[document_id].find(word)->first)][document_id] += inv_word_count;
  31.     }
  32.     documents_.emplace(document_id, DocumentData{ ComputeAverageRating(ratings), status });
  33.     order_addition_document_.insert(document_id);
  34. }
  35.  
  36. vector<Document> SearchServer::FindTopDocuments(const string_view raw_query, DocumentStatus status) const {
  37.     return FindTopDocuments(raw_query, [status](int document_id, DocumentStatus document_status, int rating) {
  38.         return document_status == status;
  39.         });
  40. }
  41.  
  42. vector<Document> SearchServer::FindTopDocuments(const string_view raw_query) const {
  43.     return FindTopDocuments(raw_query, DocumentStatus::ACTUAL);
  44. }
  45.  
  46. int SearchServer::GetDocumentCount() const {
  47.     return documents_.size();
  48. }
  49.  
  50. const map<string_view, double>& SearchServer::GetWordFrequencies(int document_id) const {
  51.     if (!documents_.count(document_id)) {
  52.         static map<string_view, double> empty;
  53.         return empty;
  54.     }
  55.     return (map<string_view, double>&) word_frequencies_in_document_.at(document_id);
  56. }
  57.  
  58. set<int>::const_iterator SearchServer::begin() {
  59.     return order_addition_document_.begin();
  60. }
  61.  
  62. set<int>::const_iterator SearchServer::end() {
  63.     return order_addition_document_.end();
  64. }
  65.  
  66. void SearchServer::RemoveDocument(int document_id) {
  67.     SearchServer::RemoveDocument(execution::seq, document_id);
  68. }
  69.  
  70. void SearchServer::RemoveDocument(execution::sequenced_policy, int document_id) {
  71.     if (!documents_.count(document_id)) {
  72.         throw invalid_argument("Документа с указанным id не существует.");
  73.     }
  74.     // log(количество документов) * количество слов в удаляемом документе,
  75.     // т.к. у каждого документа свой словарь
  76.     for (const auto& [word, freq] : word_frequencies_in_document_.at(document_id)) {
  77.         // log(количество слов во всех документах)
  78.         word_to_document_freqs_[word].erase(document_id);
  79.     }
  80.     word_frequencies_in_document_.erase(document_id);
  81.     documents_.erase(document_id);
  82.     order_addition_document_.erase(document_id);
  83. }
  84.  
  85. void SearchServer::RemoveDocument(execution::parallel_policy, int document_id) {
  86.     if (!documents_.count(document_id)) {
  87.         throw invalid_argument("Документа с указанным id не существует.");
  88.     }
  89.     // для распараллеливания for
  90.     map<string, double, less<>>& frequency_word_in_each_document = word_frequencies_in_document_.at(document_id); // частоты слов в документе
  91.     vector<const string*> words(frequency_word_in_each_document.size());
  92.     // параллельное перекладывание указателей на слова в вектор
  93.     transform(execution::par, frequency_word_in_each_document.begin(), frequency_word_in_each_document.end(),
  94.         words.begin(),
  95.         [](const pair<const string&, double>& ptr_to_word) {
  96.             return &ptr_to_word.first;
  97.         });
  98.     // удаление указанного id из ассоциаций с каждым словом
  99.     for_each(execution::par, words.begin(), words.end(),
  100.         [this, document_id](const string* word) {
  101.             word_to_document_freqs_[*word].erase(document_id);
  102.         });
  103.     word_frequencies_in_document_.erase(document_id);
  104.     documents_.erase(document_id);
  105.     order_addition_document_.erase(document_id);
  106. }
  107.  
  108. tuple<vector<string_view>, DocumentStatus> SearchServer::MatchDocument(const string_view raw_query, int document_id) const {
  109.     return MatchDocument(execution::seq, raw_query, document_id);
  110. }
  111.  
  112. tuple<vector<string_view>, DocumentStatus> SearchServer::MatchDocument(execution::sequenced_policy policy,
  113.     const string_view raw_query, int document_id) const {
  114.     //LOG_DURATION_STREAM("MatchDocument"s, cout);
  115.     if (document_id < 0 || word_frequencies_in_document_.count(document_id) == 0) {
  116.         throw out_of_range("Документа с указанным id не существует.");
  117.     }
  118.     const Query query = ParseQuery(raw_query);
  119.     if (any_of(policy, query.minus_words.begin(), query.minus_words.end(),
  120.         [this, document_id](const string_view minus_word) {
  121.             return word_to_document_freqs_.at(minus_word).count(document_id);
  122.         })) {
  123.         return { {}, documents_.at(document_id).status };
  124.     }
  125.     vector<string_view> matched_words(query.plus_words.size());
  126.  
  127.     vector<string_view>::iterator end_new_size = copy_if(policy, query.plus_words.begin(), query.plus_words.end(),
  128.         matched_words.begin(),
  129.         [this, document_id](const string_view plus_word) {
  130.             return word_to_document_freqs_.at(plus_word).count(document_id);
  131.         });
  132.  
  133.     matched_words.resize(distance(matched_words.begin(), end_new_size));
  134.     set<string_view> unique_words(matched_words.begin(), matched_words.end());
  135.  
  136.     return { vector<string_view> { unique_words.begin(), unique_words.end() }, documents_.at(document_id).status };
  137. }
  138.  
  139. tuple<vector<string_view>, DocumentStatus> SearchServer::MatchDocument(execution::parallel_policy policy,
  140.     const string_view raw_query, int document_id) const {
  141.     if (document_id < 0 || word_frequencies_in_document_.count(document_id) == 0) {
  142.         throw out_of_range("Документа с указанным id не существует.");
  143.     }
  144.     Query query = ParseQuery(raw_query, false);
  145.  
  146.     if (any_of(policy, query.minus_words.begin(), query.minus_words.end(),
  147.         [this, document_id](const string_view minus_word) {
  148.             return word_to_document_freqs_.at(minus_word).count(document_id);
  149.         })) {
  150.         return { {}, documents_.at(document_id).status };
  151.     }
  152.     vector<string_view> matched_words(query.plus_words.size());
  153.  
  154.     vector<string_view>::iterator end_new_size = copy_if(policy, query.plus_words.begin(), query.plus_words.end(),
  155.         matched_words.begin(),
  156.         [this, document_id](const string_view plus_word) {
  157.             return word_to_document_freqs_.at(plus_word).count(document_id);
  158.         });
  159.  
  160.     matched_words.resize(distance(matched_words.begin(), end_new_size));
  161.     set<string_view> unique_words(matched_words.begin(), matched_words.end());
  162.  
  163.     return { vector<string_view> { unique_words.begin(), unique_words.end() }, documents_.at(document_id).status };
  164. }
  165.  
  166. bool SearchServer::IsStopWord(const string_view word) const {
  167.     return stop_words_.count(word) > 0;
  168. }
  169.  
  170. vector<string_view> SearchServer::SplitIntoWordsNoStop(const string_view text) const {
  171.     vector<string_view> words;
  172.     for (const string_view word : SplitIntoWords(text)) {
  173.         if (!IsStopWord(word)) {
  174.             words.push_back(word);
  175.         }
  176.     }
  177.     return words;
  178. }
  179.  
  180. int SearchServer::ComputeAverageRating(const vector<int>& ratings) {
  181.     if (ratings.empty()) {
  182.         return 0;
  183.     }
  184.     int rating_sum = accumulate(ratings.begin(), ratings.end(), 0);
  185.     return rating_sum / static_cast<int>(ratings.size());
  186. }
  187.  
  188. SearchServer::QueryWord SearchServer::ParseQueryWord(std::string_view text) const {
  189.     bool is_minus = false;
  190.     // Word shouldn't be empty
  191.     if (text.empty()) {
  192.         throw invalid_argument("Присутствует пустое слово в запросе.");
  193.     }
  194.     if (text[0] == '-') {
  195.         if (text[1] == '-') {
  196.             throw invalid_argument("Запрос содержит два знака \"-\" подряд.");
  197.         }
  198.         is_minus = true;
  199.         text = text.substr(1);
  200.     }
  201.     return { text, is_minus, IsStopWord(text) };
  202. }
  203.  
  204. SearchServer::Query SearchServer::ParseQuery(const string_view text, bool sequenced_policy) const {
  205.     Query query;
  206.     for (const string_view word : SplitIntoWords(text)) {
  207.         if (!IsValidWord(word)) {
  208.             throw invalid_argument("Некорректный поисковый запрос.");
  209.         }
  210.         if (word == "-"s) {
  211.             throw invalid_argument("После знака \"-\" отсутствует слово.");
  212.         }
  213.         QueryWord query_word = ParseQueryWord(word);
  214.         if (!query_word.is_stop) {
  215.             if (query_word.is_minus) {
  216.                 query.minus_words.push_back(query_word.data);
  217.             } else {
  218.                 query.plus_words.push_back(query_word.data);
  219.             }
  220.         }
  221.     }
  222.     if (sequenced_policy) {
  223.         sort(query.plus_words.begin(), query.plus_words.end());
  224.         query.plus_words.erase(unique(query.plus_words.begin(), query.plus_words.end()), query.plus_words.end());
  225.  
  226.         sort(query.minus_words.begin(), query.minus_words.end());
  227.         query.minus_words.erase(unique(query.minus_words.begin(), query.minus_words.end()), query.minus_words.end());
  228.     }
  229.     return query;
  230. }
  231.  
  232. double SearchServer::ComputeWordInverseDocumentFreq(const string_view word) const {
  233.     return log(GetDocumentCount() * 1.0 / word_to_document_freqs_.at(word).size());
  234. }
  235.  
  236. bool SearchServer::IsValidWord(const string_view word) {
  237.     // A valid word must not contain special characters
  238.     return none_of(word.begin(), word.end(), [](char c) {
  239.         return c >= '\0' && c < ' ';
  240.     });
  241. }
Advertisement
Add Comment
Please, Sign In to add comment