Advertisement
chevengur

СПРИНТ № 1 | Лямбда-функции | Урок 8: Ранжирование по TF-IDF

Oct 3rd, 2023 (edited)
331
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.78 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <set>
  4. #include <string>
  5. #include <utility>
  6. #include <vector>
  7. #include <map>
  8. #include <cmath>
  9.  
  10. using namespace std;
  11.  
  12. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  13.  
  14. string ReadLine() {
  15.     string s;
  16.     getline(cin, s);
  17.     return s;
  18. }
  19.  
  20. int ReadLineWithNumber() {
  21.     int result = 0;
  22.     cin >> result;
  23.     ReadLine();
  24.     return result;
  25. }
  26.  
  27. vector<string> SplitIntoWords(const string& text) {
  28.     vector<string> words;
  29.     string word;
  30.     for (const char c : text) {
  31.         if (c == ' ') {
  32.             if (!word.empty()) {
  33.                 words.push_back(word);
  34.                 word.clear();
  35.             }
  36.         }
  37.         else {
  38.             word += c;
  39.         }
  40.     }
  41.     if (!word.empty()) {
  42.         words.push_back(word);
  43.     }
  44.  
  45.     return words;
  46. }
  47.  
  48. struct Document {
  49.     int id;
  50.     double relevance;
  51. };
  52.  
  53. class SearchServer {
  54. public:
  55.     void SetStopWords(const string& text) {
  56.         for (const string& word : SplitIntoWords(text)) {
  57.             stop_words_.insert(word);
  58.         }
  59.     }
  60.  
  61.     void AddDocument(int document_id, const string& document) {
  62.         ++document_count_;
  63.         const auto words = ParseQuery(document);
  64.         auto tf = 1.0/words.plus_word.size();
  65.         for (const auto& word : words.plus_word) {
  66.             word_to_document_freqs_[word][document_id] += tf;
  67.         }
  68.     }
  69.  
  70.     vector<Document> FindTopDocuments(const string& raw_query) const {
  71.         auto query_words = ParseQuery(raw_query);
  72.         auto matched_documents = FindAllDocuments(query_words);
  73.  
  74.         sort(matched_documents.begin(), matched_documents.end(),
  75.             [](const Document& lhs, const Document& rhs) {
  76.                 return lhs.relevance > rhs.relevance;
  77.             });
  78.         if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  79.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  80.         }
  81.         return matched_documents;
  82.     }
  83.  
  84. private:
  85.  
  86.     struct Query {
  87.         set<string>minus_word;
  88.         set<string>plus_word;
  89.     };
  90.    
  91.     int document_count_ = 0;
  92.     map<string, map<int, double>> word_to_document_freqs_;
  93.  
  94.     set<string> stop_words_;
  95.  
  96.     bool IsStopWord(const string& word) const {
  97.         return stop_words_.count(word) > 0;
  98.     }
  99.  
  100.     vector<string> SplitIntoWordsNoStop(const string& text) const {
  101.         vector<string> words;
  102.         for (const string& word : SplitIntoWords(text)) {
  103.             if (!IsStopWord(word)) {
  104.                 words.push_back(word);
  105.             }
  106.         }
  107.         return words;
  108.     }
  109.  
  110.     Query ParseQuery(const string& text) const {
  111.         Query query_words;
  112.         for (const string& word : SplitIntoWordsNoStop(text)) {
  113.             if (word[0] == '-') {
  114.                 query_words.minus_word.insert(word.substr(1));
  115.             }
  116.             else {
  117.                 query_words.plus_word.insert(word);
  118.             }
  119.  
  120.         }
  121.         return query_words;
  122.     }
  123.  
  124.     double IDF(const string& word) const {
  125.         return static_cast<double> (log(document_count_ * 1.0 / word_to_document_freqs_.at(word).size()));
  126.     }
  127.  
  128.  
  129.     vector<Document> FindAllDocuments(const Query& words) const {
  130.         vector<Document> matched_documents;
  131.         map<int, double> document_to_relevance;
  132.         for (const auto& word : words.plus_word) {
  133.             if (word_to_document_freqs_.count(word) == 0) {
  134.                 continue;
  135.             }
  136.             const double idf = IDF(word);
  137.             for (const auto& [id, tf] : word_to_document_freqs_.at(word)) {
  138.                 document_to_relevance[id] += tf * idf;
  139.             }
  140.         }
  141.         for (const auto& mid : words.minus_word) {
  142.             if (word_to_document_freqs_.count(mid) == 0) {
  143.                 continue;
  144.             }
  145.             for (const auto& [id, value] : word_to_document_freqs_.at(mid)) {
  146.                 document_to_relevance.erase(value);
  147.             }
  148.  
  149.         }
  150.         for (const auto& [key, value] : document_to_relevance) {
  151.             matched_documents.push_back({ key, value });
  152.         }
  153.         return matched_documents;
  154.     }
  155. };
  156.  
  157. SearchServer CreateSearchServer() {
  158.     SearchServer search_server;
  159.     search_server.SetStopWords(ReadLine());
  160.  
  161.     const int document_count = ReadLineWithNumber();
  162.     for (int document_id = 0; document_id < document_count; ++document_id) {
  163.         search_server.AddDocument(document_id, ReadLine());
  164.     }
  165.  
  166.     return search_server;
  167. }
  168.  
  169. int main() {
  170.     const SearchServer search_server = CreateSearchServer();
  171.  
  172.     const string query = ReadLine();
  173.  
  174.     for (const auto& [document_id, relevance] : search_server.FindTopDocuments(query)) {
  175.         cout << "{ document_id = "s << document_id << ", "
  176.             << "relevance = "s << relevance << " }"s << endl;
  177.     }
  178. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement