Search code examples
c++c++20std-ranges

Is there any standard functionality for creating a flattened view of a map with a container as the mapped_type?


Is there any standard functionality to create a range/view over all pairs? The following code illustrates the view I am looking to create:

std::unordered_map<std::string, std::vector<int>> m{{"Foo", {1,2}}, {"Hello", {4,5}}};
auto view = ???;
std::vector<std::pair<std::string, int>> v{view.begin(), view.end()};
std::vector<std::pair<std::string, int>> out1{{"Foo", 1}, {"Foo", 2}, {"Hello", 4}, {"Hello", 5}};
std::vector<std::pair<std::string, int>> out2{{"Hello", 4}, {"Hello", 5}, {"Foo", 1}, {"Foo", 2}};
assert(v == out1 || v == out2);

Note: It is trivial to write a nested for loop to iterate over this structure.


Solution

  • Yes, combine std::ranges::views::join with std::ranges::views::transform and some lambdas.

    using namespace std::ranges::views;
    auto to_pairs = [](auto & pair){ 
        auto to_pair = [&key=pair.first](auto & value){ return std::pair{ key, value }; };
        return pair.second | transform(to_pair); 
    };
    auto view = m | transform(to_pairs) | join | common;