Reputation: 2271
I need to replace multiple values inside an STL map
but I haven't found anything useful in <algorithm>
.
Pseudocode:
Input:
map<type1, type2> m1;
m1[k1] = v1;
m1[k2] = v2;
m1[k3] = v3;
map<type1, type2> m2;
m2[k1] = v5;
m2[k3] = v4;
Action:
merge(m1, m2)
Output:
m1[k1] = v5;
m1[k2] = v2;
m1[k3] = v4;
The merge
method should replace m1
values with m2
values when keys match.
I read documentation of merge but it seems to me not usable with maps.
Upvotes: 0
Views: 403
Reputation: 93274
C++17 adds std::map::merge
, which does what you want:
template<class C2> void merge(std::map<Key, T, C2, Allocator>& source);
Attempts to extract ("splice") each element in source and insert it into *this using the the comparison object of *this. If there is an element in *this with key equivalent to the key of an element from source, then that element is not extracted from source. No elements are copied or moved, only the internal pointers of the container nodes are repointed. All pointers and references to the transferred elements remain valid, but now refer into *this, not into source.
Example:
map<std::string, int> m1;
m1["k1"] = 1;
m1["k2"] = 2;
m1["k3"] = 3;
map<std::string, int> m2;
m2["k1"] = 5;
m2["k3"] = 4;
m2.merge(m1);
for(const auto& p : m2)
{
std::cout << p.first << " -> " << p.second << "\n";
}
Will print:
k1 -> 5
k2 -> 2
k3 -> 4
Here's a C++14 solution I came up with:
template <typename TMap0, typename TMap1>
auto merge(TMap0&& m0, TMap1&& m1)
{
using map_type = std::remove_reference_t<TMap0>;
// Move or copy `m0` into `result`.
map_type result(std::forward<TMap0>(m0));
// For each pair in `m1`...
for(auto&& p : m1)
{
// If `m0` contains the key `p.first`...
if(m0.count(p.first) != 0)
{
// Move or copy `p.second` into `result`.
result[p.first] = forward_like<TMap1>(p.second);
}
}
return result;
}
(forward_like
can be found here.)
Example:
map<std::string, int> m1;
m1["k1"] = 1;
m1["k2"] = 2;
m1["k3"] = 3;
map<std::string, int> m2;
m2["k1"] = 5;
m2["k3"] = 4;
auto res = merge(m1, m2);
for(const auto& p : res)
{
std::cout << p.first << " -> " << p.second << "\n";
}
Will print:
k1 -> 5
k2 -> 2
k3 -> 4
Upvotes: 3