Firstly, you'll want to be able to hash multiple key fields to provide one high quality hash value, and - in the style of boost hash_combine
- you can do that with:
template <class T>
inline void hash_combine(std::size_t& seed, T const& v) {
seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
...combined with a general-purpose tuple
hash function...
struct hash_tuple {
auto operator()(const auto& tuple) const {
std::size_t seed = 0;
std::apply([&](const auto& ...element){(..., hash_combine(seed, element));}, tuple);
return seed;
}
};
The above will work for any length of tuple, and any contained types that are themselves hashable.
You can then either use an unordered_map
from a std::tuple
of your key fields to the price double
, as in:
using key = std::tuple<std::string, std::string, std::string>;
std::unordered_map<key, double, hash_tuple> m;
// ...then just use the map...
m[{"abc", "def", "ghi"}] = 3.14;
...or, you might want to have a struct
with your keys and price combined...
struct X {
std::string a, b, c;
double price_;
auto tie_keys() const { return std::tie(a, b, c); }
bool operator==(const X& rhs) const {
return tie_keys() == rhs.tie_keys();
}
friend std::ostream& operator<<(std::ostream& os, const X& x) {
return os << x.a << ' ' << x.b << ' ' << x.c << ' ' << x.price_;
}
};
...and store those in an unordered_set<>
...
auto hash_fn = [](const X& x) { return hash_tuple{}(x.tie_keys()); };
std::unordered_set<X, decltype(hash_fn)> m2;
// ...and use it...
m2.emplace("ab", "cde", "fg", 3.14);
m2.emplace("hij", "kl", "mn", 2.71);
for (const auto& x : m2)
std::cout << x << '\n';
You'll need various headers of course...
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <tuple>
does having 3 keys affect the search time complexity for the map?
Not if you have a decent hash function.