Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- SearchServer::PlusMinusWords SearchServer::ParseQuery(const std::string& raw_query) const {
- SearchServer::PlusMinusWords query_words;
- ThrowSpecialSymbolInText(raw_query);
- // это нужно, чтобы и плюс-, и минус-слова в своих векторах были уже отсортированы, потому что далее их ждет unique-erase
- std::vector<std::string> sorted_query_words = SplitIntoWordsNoStop(raw_query); // вот это гарантировало бы, что минус-слова попадут в контейнер с минус-словами раньше, и можно было бы проверять, когда добавляешь плюс-слово, что оно не находится в минус-словах; но тут уже другое -- если слово есть и с минусом и без минуса, я кем его должен считать?
- // остается просто забить за вероятность, что минус слово окажется и плюс словом
- std::sort(std::execution::par,
- sorted_query_words.begin(), sorted_query_words.end());
- for (const std::string& word : sorted_query_words) {
- if (word[0] == '-') {
- auto minus_word = word.substr(1);
- if (minus_word.empty() || minus_word[0] == '-') {
- throw std::invalid_argument("Alone or double minus in query"s);
- }
- query_words.minus_words.push_back(minus_word);
- } else { /* else if (query_words.minus_words.count(word) == 0) // было тут вместо else, чтобы защитить плюс-слова от проникновения минус-слова, которое подано в запросе без минуса (запрос же автоматически генерируется) */
- query_words.plus_words.push_back(word);
- }
- }
- std::vector<std::string>::iterator last;
- // чистим минус-слова от дубликатов
- last = std::unique(query_words.minus_words.begin(), query_words.minus_words.end());
- query_words.minus_words.erase(last, query_words.minus_words.end());
- // чистим плюс-слова от дубликатов
- last = std::unique(query_words.plus_words.begin(), query_words.plus_words.end());
- query_words.plus_words.erase(last, query_words.plus_words.end());
- return query_words;
- }
- // ===========================================================================================================================
- std::tuple<std::vector<std::string>, DocumentStatus> SearchServer::MatchDocument(std::execution::parallel_policy, const std::string& raw_query, int document_id) const {
- if (IsNegativeDocumentId(document_id)) {
- throw std::invalid_argument("Negative document id"s);
- }
- if (IsNonexistentDocumentId(document_id)) {
- throw std::invalid_argument("Nonexistent document id"s);
- }
- // тут два отсортированных вектора с уникальными + и - словами
- SearchServer::PlusMinusWords prepared_query = ParseQuery(raw_query);
- // вытягиваю слова документа из сервера, других вариантов кроме как по map пройтись у меня нет
- std::vector<const std::string*> words(TF_by_id_.at(document_id).size());
- std::transform(std::execution::par,
- TF_by_id_.at(document_id).begin(), TF_by_id_.at(document_id).end(),
- words.begin(),
- [](auto& item) { return &item.first; });
- bool is_minus_words_in_document = any_of(std::execution::par, words.begin(), words.end(),
- [&prepared_query](const std::string* word) {
- return count(std::execution::par, // у меня же теперь вектор! запускаю параллельный ЛИНЕЙНЫЙ поиск (а был set, где поиск шел за log)
- prepared_query.minus_words.begin(),
- prepared_query.minus_words.end(),
- *word);
- }
- );
- if (is_minus_words_in_document) {
- return {std::vector<std::string>{}, document_info_.at(document_id).status};
- }
- std::vector<const std::string*> result_intersection_ptrs(std::min(prepared_query.plus_words.size(), words.size()));
- std::copy_if(std::execution::par, words.begin(), words.end(),
- result_intersection_ptrs.begin(),
- [&prepared_query](const std::string* word) {
- return count(std::execution::par,
- prepared_query.plus_words.begin(),
- prepared_query.plus_words.end(),
- *word);
- }
- );
- std::vector<std::string> result_intersection(result_intersection_ptrs.size());
- std::transform(std::execution::par,
- result_intersection_ptrs.begin(), result_intersection_ptrs.end(),
- result_intersection.begin(),
- [](const std::string* word) { return word != nullptr ? *word : ""s; });
- std::sort(std::execution::par,
- result_intersection.begin(), result_intersection.end());
- // найдем первое не пустое слово
- auto start = std::upper_bound(result_intersection.begin(), result_intersection.end(), ""s);
- // вариант 1: ratio 1.55
- std::vector<std::string> result;
- std::move(start, result_intersection.end(), std::back_inserter(result));
- return {result, document_info_.at(document_id).status};
- // // вариант 2: ratio 1.66
- // return {{start, result_intersection.end()}, document_info_.at(document_id).status};
- // // вариант 3: неправильный результат
- // // Решение упало. Assertion failed: 15360 != 15280
- // // hint: results mismatch 1 unit tests failed. Terminate
- // // подсказка: Неправильно распараллелен метод MatchDocument
- // auto last = std::unique(result_intersection.begin(), result_intersection.end());
- // result_intersection.erase(last, result_intersection.end());
- // result_intersection.erase(result_intersection.begin()); // стереть пустую строку из начала
- // return {result_intersection, document_info_.at(document_id).status};
- }
- //===========================================================================================================================
- std::tuple<std::vector<std::string>, DocumentStatus> SearchServer::MatchDocument(const std::string& raw_query, int document_id) const {
- ThrowSpecialSymbolInText(raw_query);
- if (IsNegativeDocumentId(document_id)) {
- throw std::invalid_argument("Negative document id"s);
- }
- if (IsNonexistentDocumentId(document_id)) {
- throw std::invalid_argument("Nonexistent document id"s);
- }
- SearchServer::PlusMinusWords prepared_query = ParseQuery(raw_query);
- for (const std::string& minus_word : prepared_query.minus_words) {
- if (TF_by_term_.count(minus_word) > 0) {
- if (TF_by_term_.at(minus_word).count(document_id) > 0) {
- return {std::vector<std::string>{}, document_info_.at(document_id).status};
- }
- }
- }
- std::set<std::string> plus_words_in_document;
- for (const std::string& plus_word : prepared_query.plus_words) {
- if (TF_by_term_.count(plus_word) == 1) {
- if (TF_by_term_.at(plus_word).count(document_id) == 1) {
- plus_words_in_document.insert(plus_word);
- }
- }
- }
- std::vector<std::string> result_intersection; // интересно, если + слов как и - слов в документе не оказалось, пихать неинициализированный result_intersection это нормально?
- for (const std::string& word : plus_words_in_document) {
- result_intersection.push_back(word);
- }
- return {result_intersection, document_info_.at(document_id).status};
- }
- std::tuple<std::vector<std::string>, DocumentStatus> SearchServer::MatchDocument(std::execution::sequenced_policy, const std::string& raw_query, int document_id) const {
- return MatchDocument(raw_query, document_id);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement