I know that I can create a multi-dimensional map by nesting maps together, e.g.:
// Two-dimensional key
map<string, map<int, double> > m;
so it is easy to extract all of the values associated to the highest order key. So if I have a set of data that looks like this:
A1 : 23.0
A2 : 45.3
A5 : 5.88
B9 : 7.2
B10 : 79.74
I could store it as std::map<std::string, std::map<uint, float>> mymap
and easily retrieve all of the A
values by doing mymap["A"]
.
I also know I can create a std::map
with multiple keys by using a std::tuple
, which is more intuitive:
std::map<std::tuple<std::string,uint>, float> mymap
but is there a c 14
way to get all of the A
elements with this second implementation?
CodePudding user response:
std::map<std::tuple<std::string,uint>, float> mymap
I'm assuming uint
means unsigned int
.
For this particular case, map::lower_bound
and map::upper_bound
may be combined:
auto beg = mymap.lower_bound({"A",0});
auto end = mymap.upper_bound({"A", static_cast<unsigned>(-1)});
for(auto it = beg; it != end; it) {
std::cout << it->second << '\n'; // only "A" records
}
lower_bound
will return an iterator to the first element not less than the given key, which is the first possible validA
entry,{"A", 0}
.upper_bound
will return an iterator to the first element greater than the given key, which is the last possible validA
entry,{"A", (unsigned) -1}
.
CodePudding user response:
You can use std::map::equal_range
. It requires you to provide a transparent comparator, which is easy to make:
#include <cstdio>
#include <map>
#include <string>
#include <utility>
using Key = std::pair<std::string, int>;
struct Cmp {
bool operator()(Key const& e1, std::string const& e2) const noexcept {
return e1.first < e2;
}
bool operator()(std::string const& e1, Key const& e2) const noexcept {
return e1 < e2.first;
}
bool operator()(Key const& e1, Key const& e2) const noexcept {
return e1 < e2;
}
using is_transparent = bool;
};
int main() {
std::map<Key, float, Cmp> map;
map.insert({{"A", 1}, 23.0F});
map.insert({{"A", 2}, 45.3F});
map.insert({{"A", 5}, 5.88F});
map.insert({{"B", 9}, 7.20F});
map.insert({{"B", 10}, 79.74F});
auto const rng = map.equal_range("A");
for (auto it = rng.first; it != rng.second; it) {
std::printf("%s%d : %.2f\n",
it->first.first.c_str(),
it->first.second,
it->second);
}
}