Home > Net >  Implement multi-dimensional std::map with std::tuple and view access
Implement multi-dimensional std::map with std::tuple and view access

Time:08-20

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 valid A entry, {"A", 0}.

  • upper_bound will return an iterator to the first element greater than the given key, which is the last possible valid A 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);
    }
}
  • Related