Seredenko-V

Untitled

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