Seredenko-V

search_server_cpp

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