Is there a way to construct a map with two ranges in C ? That is, instead of calling a default constructor and consequently inserting elements to a map:
for (size_t i = 0; i < Vector_1.size() && i < Vector_2.size(); i ) {
mymap[Vector_1[i]] = Vector_2[i];
}
I'd like to build a map in place by calling some sort of a constructor which would take two ranges as arguments, something like this:
std::map<t1, t2> mymap(Vector_1.begin(), Vector_1.end(), Vector_2.begin(), Vector_2.end());
Or:
mymap.insert(Vector_1.begin(), Vector_1.end(), Vector_2.begin(), Vector_2.end());
I haven't found any, but maybe there is still a way to do it. Is there a shortcut to initialize a map from two ranges, or at least insert two ranges into a map?
CodePudding user response:
You could use Eric Niebler's range-v3 library, zip the two vectors in a view, and write that view out to a map.
#include <fmt/ranges.h>
#include <map>
#include <range/v3/all.hpp>
#include <vector>
int main() {
std::vector<char> cs{'a', 'b', 'c'};
std::vector<int> is{1, 2, 3};
auto m{ ranges::views::zip(cs, is) | ranges::to<std::map<char, int>>() };
fmt::print("{}", m);
}
// Outputs: {'a': 1, 'b': 2, 'c': 3}
As Armin Montigny indicated, the std::ranges::views::zip
won't be available until C 23; and the same happens with std::ranges::to
. Here you can see some compilers already implement std::ranges::views::zip
but not yet std::ranges::to
.
CodePudding user response:
Is there a shortcut to initialize a map from two ranges, or at least insert two ranges into a map?
It is straightforward to create your own "shortcut", which typically takes the form of a free function.
#include <cassert>
#include <vector>
#include <list>
#include <map>
#include <ranges>
#include <iostream>
template <std::ranges::range K, std::ranges::range V>
std::map<std::ranges::range_value_t<K>, std::ranges::range_value_t<V>> createMapFromRanges(K&& krng, V&& vrng)
{
std::map<std::ranges::range_value_t<K>, std::ranges::range_value_t<V>> map;
assert(std::size(krng) == std::size(vrng));
auto [k, kend] = std::tuple{krng.begin(), krng.end()};
auto [v, vend] = std::tuple{vrng.begin(), vrng.end()};
while (k != kend && v != vend)
map.emplace(*k ,*v );
return map;
}
int main()
{
auto map = createMapFromRanges(std::vector<int>{1,2,3}, std::list<int>{4,5,6});
for (auto& elem : map) {
std::cout << elem.first << '/' << elem.second << '\n';
}
return 0;
}
P.S. I see many posts referencing other libraries (e.g. boost
, range-v3
) or unsupported features (e.g. zip_view
). Certainly, I am in favor of reusing high quality libraries. Unfortunately, many projects simply cannot use them (i.e. restricted by the organization).