What I need:
I need a lookup table. Once the keywords are all found, then the value of the std::unordered_map
is returned.And I don't care about the sequence of the strings in the std::vector
.
I think std::unordered_map<std::vector<std::string>, int>
could achieve this goal. Any better method to achieve this goal? Or any improvement for this code snippet?
#include <string>
#include <unordered_map>
#include <vector>
#include <iostream>
class Hash
{
public:
std::size_t operator()(const std::vector<std::string>& vec) const
{
std::hash<std::string> hasher;
std::size_t hash_value{};
for(auto itr = vec.begin(); itr!=vec.end(); itr++)
{
hash_value ^= (hasher(*itr)); //Why `hash_value ^= ((hasher(*itr))<<1);` does not influence the output of mp.find(to_search)
}
return hash_value;
}
};
class Equal
{
public:
bool operator()(const std::vector<std::string>& vec1, const std::vector<std::string>& vec2) const
{
bool ret = true;
if(vec1.size() != vec2.size())
{
ret = false;
}
else
{
for(auto itr_outer = vec1.begin(); itr_outer!=vec1.end(); itr_outer++)
{
bool found = false;
for(auto itr_inner = vec1.begin(); itr_inner!=vec2.end(); itr_inner++)
{
if(*itr_outer == *itr_inner)
{
found = true;
break;
}
}
if(!found)
{
ret = false;
break;
}
}
}
return ret;
}
};
int main()
{
const std::unordered_map<std::vector<std::string>, int, Hash, Equal> mp = {
{{"hello word"}, 1},
{{"thanks a lot", "I need some help"}, 2},
{{"how to make it better"}, 3},
};
std::vector<std::string> to_search = {"I need some help", "thanks a lot"};
auto itr = mp.find(to_search);
if(itr!=mp.end())
{
std::cout <<"found:" << itr->second << std::endl;
}
else
{
std::cout << "not found" << std::endl;
}
}
```
std::unordered_set
instead of a vector; lookup is faster, and you say you don't care about sequence. If each string exists, and the size is equal, you have equality, as no duplicates can happen. \$\endgroup\$std::unordered_set
is faster, could you please explain that in more detail for me? \$\endgroup\$std::unordered_set
uses a hash to check if a key (here: one of your strings) is inside already. This is faster than looping through the vector and doing a string compare for each element. Note: I meant inside your map - not instead. You would use astd::unordered_map<std::unordered_set<std::string>,int>
. \$\endgroup\$std::string::operator==()
is implemented? If I understand you correctly, the goal is achieved by comparing byte one by one other than by comparing hash. But I think it's not the main point, whystd::set
is better for this post is because that it could avoid to loop through the vector of strings. Am I right? \$\endgroup\$