C++ remove certain elements of vector - c++

I am new to C++ and want to do vector element elimination.
My vectors are like:
<vector<vector>> objPoints;
<vector<vector>> delPoints;
<vector<vector>> objPoints2;
each objPoints has size 1000x3 and has all points. From objPoints i want to remove delPoints i.e. the (X,Y,Z) values that reside in each row.
Can anyone please tell me syntax?

I interpret your questions as follows: You have two vectors objPoints and delPoints which contain 1000 three-dimensional points. I would encode this as
std::vector<std::array<int,3> > objPoints;
where I assumed you have some raster such that you can desribe your points by int values (otherwise, for double entries, comparison is not that easy).
One benefit of using std::array<int,3> is that you automatically get a lexicographic ordering of the points (that means, specializations of std::less and std::equal_to which can directly be used without the further need to create some).
Algorithm:
First sort your arrays. There might be algorithms where this is not really necessary (see the other answer by #AshwaniDausodia), but the following assumes it. Further, in general by using sorted vectors one can obtain a better performance (at least in the big-O: for unsorted containers, it is roughly O(size1*size2), whereas it is lower for the following algorithm). The sorting first requires an effort of O(size1 log(size1)) + O(size2 log(size2))
Next, traverse both arrays at the same time and each time you find a common element delete it from one of the vectors. As you traverse sorted arrays, where you can always increase only the iterator pointing to the smaller element, this step takes O(size1+size2).
Implementation:
// deletes the elements from container c1 which are also present in c2
// requires sorted containers c1 and c2
//
template< class ContainerType1, class ContainerType2 >
void delete_common_elements(ContainerType1& c1, ContainerType2 const& c2 )
{
for(auto it1=c1.begin(), it2=c2.begin()
; it1!=c1.end() && it2!=c2.end(); )
{
if(*it1==*it2) // eventually change here if your points are not int's
// but are of floating-point type
{
it1 = c1.erase(it1); //it1 is increased here
}
else
{
*it1<*it2 ? ++it1 : ++it2;
}
}
}
DEMO
All together, this requires an effort of O(c1.size()) + O(c1.size() * log(c1.size()) (naturally assuming c1.size()>=c2.size()).
One can easily extend this to take an arbitrary comparison operator instead of the operator==.

If you definately have to use vectors, an easy (but inefficient) way would be to std::find the element in objPoints that you want to remove and then remove it with std::vector::erase.

You may consider read this Q&A on StackOverflow on how to erase elements from STL containers.
The key point is to use the erase-remove idiom to erase items from the vector, and use a lambda to express the erasing condition:
objPoints.erase(
std::remove_if(
objPoints.begin(),
objPoints.end(),
[&delPoints](const Point3D& point)
{
// Erasing condition:
// Is 'point' contained in the 'delPoints' vector?
auto it = std::find(delPoints.begin(), delPoints.end(), point);
return (it != delPoints.end());
}),
objPoints.end());
Full compilable code sample (live here):
#include <algorithm> // for std::find(), std::remove_if()
#include <array> // for std::array
#include <iostream> // for console output
#include <vector> // for std::vector
typedef std::array<int, 3> Point3D;
std::ostream& operator<<(std::ostream& os, const Point3D& point)
{
os << "{" << point[0] << ", "
<< point[1] << ", " << point[2] << "}";
return os;
}
std::ostream& operator<<(std::ostream& os, const std::vector<Point3D>& v)
{
if (v.empty())
{
os << "{ <empty> }" << std::endl;
return os;
}
os << "{\n";
for (const auto& point : v)
{
os << " " << point << '\n';
}
os << "}" << std::endl;
return os;
}
int main()
{
std::vector<Point3D> objPoints{{1, 2, 3},
{4, 5, 6},
{11, 22, 33},
{44, 55, 66},
{77, 88, 99}};
std::vector<Point3D> delPoints{{10, 10, 10},
{11, 22, 33},
{44, 55, 66}};
std::cout << "objPoints =\n" << objPoints << std::endl;
std::cout << "delPoints =\n" << delPoints << std::endl;
objPoints.erase(
std::remove_if(
objPoints.begin(),
objPoints.end(),
[&delPoints](const Point3D& point)
{
// Erasing condition:
// Is 'point' contained in the 'delPoints' vector?
auto it = std::find(delPoints.begin(), delPoints.end(), point);
return (it != delPoints.end());
}),
objPoints.end());
std::cout << "\nAfter erasing, objPoints =\n";
std::cout << objPoints << std::endl;
}
Output:
objPoints =
{
{1, 2, 3}
{4, 5, 6}
{11, 22, 33}
{44, 55, 66}
{77, 88, 99}
}
delPoints =
{
{10, 10, 10}
{11, 22, 33}
{44, 55, 66}
}
After erasing, objPoints =
{
{1, 2, 3}
{4, 5, 6}
{77, 88, 99}
}

One obivious method would be:
for each point in delPoints
if point exists in objPoints
delete point from objPoints.
You can do it much more efficiently if you are allowed to sort the vectors. I will provide you with method and pseudo code then you can implement it on you own.
First sort objPoints and delpoints
i=0,j=0
while i < length(objPoints) and j < length(delPoints)
if objPoints[i] > delPoints[j] // Means delPoints[j] is not there in objPoints. If it would have, we would have found it.
j++
else if objPoints[i] < delPoints[j] // Means delPoints[j] is after objPoints[i] if it is there in objPoints
i++
else
erase objPoints[i] // Means we have found delPoints[j], so delete it.
For comaprison, first compare w.r.t x cordinate then y and then z. For sorting, you can use std::sort with same comparison function described in previous line. For deleting, you can use std::vector::erase.
Or you can implement your own fuctions.

Related

How can I print a vector in a recursive function?

I have a problem here: I am to write a function that prints the elements of a vector recursively so no loop is allowed.
I tried this code but it crashes at runtime:
void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
int main(){
vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v, v.begin());
}
If I run the program I get the assertion dialog!?
void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
The ivec parameter is passed by value. Both of these parameters are passed by value. Passing by value by means that inside the function these are copies of the original parameters.
Your main() calls this recursive function passing it its vector and the beginning iterator of its vector. However because all parameters are passed by value, each recursive iteration of the function compares the iterator to the end() of a completely different vector. Undefined behavior.
You obviously forgot to pass the vector by reference. The first parameter to should be const std::vector<int> &ivec.
When you call print, you pass the vector by value. This means that it creates an entirely new vector each time, but the iterator still comes from the original vector. Because the iterator comes from a different vector, the test it == ivec.end() is always going to fail.
We can fix this just by passing ivec by const reference:
void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it)
{
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
And the code works fine!
You have to pass the vector by reference so that to avoid multiple copies thus the iterator is guaranteed to be compared with the iterators of the same vector only not with others':
void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it) {
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
int main(){
vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v, v.begin()); // ok
vector<int>::iterator it = v.begin();
auto v2{ v };
if (it == v.begin())
cout << "it = v.begin()" << endl;
if (it == v2.begin()) // causes crash
cout << "it =v2.begin()" << endl;
}
No need to pass in two arguments to the print function. If the vector is zero-length, print nothing.
if the vector is length of 1, print that element.
if the vector is of length greater than 1, then print a smaller vector (recursively) that does not include the last character, and then print the last character.
yes, this will create a copy of the vector for each recursion, but I guess that feels more like recursion to me. Incrementing a pointer on each loop does not feel like recursion.
#include <iostream>
#include <vector>
void print(const std::vector<int> vec) {
if (!vec.size())
return;
else {
print(std::vector<int>(vec.begin(), vec.end() - 1));
std::cout << " " << *(vec.end() - 1);
}
}
int main(){
std::vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v);
}
If you just need to print the vector, I think a much more elegant solution would be to use iterators.
#include <iostream>
#include <vector>
using namespace std;
void print_vector(vector<int>::iterator it, const vector<int>::iterator &end)
{
if(it == end) {
cout << '\n';
return;
}
cout << *it << " ";
print_vector(++it, end);
}
int main() {
vector<int> v = {1,2,3,4,5,6,7,8,9};
print_vector(v.begin(), v.end());
return 0;
}
If you want to reuse the function with other structures (perhaps to impress a friend or a teacher) you can use the templates.
#include <iostream>
#include <set>
#include <vector>
using namespace std;
template<class TContainer>
void print_structure(typename TContainer::iterator it, const typename TContainer::iterator end)
{
if(it == end) {
cout << '\n';
return;
}
cout << *it << " ";
print_structure<TContainer>(++it, end);
}
int main() {
vector<int> vi = {1,2,3,4,5,6,7,8,9};
print_structure<vector<int>>(vi.begin(), vi.end());
vector<double> vd = {1.2, 3.4, 5.6, 7.8, 9.0};
print_structure<vector<double>>(vd.begin(), vd.end());
set<int> si = {10, 10, 10, 10, 20, 20, 20, 20, 30, 30, 30};
print_structure<set<int>>(si.begin(), si.end());
set<double> sd = {10.10, 10.10, 20.20, 20.20, 30.30, 3.0};
print_structure<set<double>>(sd.begin(), sd.end());
return 0;
}
Does it look like a bazooka to kill mosquitoes? Sure it is! But it's pretty crazy yeah?!

std::map: return vectors consisting of keys that have equal values

I have a std::map object. Keys are entity IDs (integers) and values their 2D positions (vectors). The aim is to identify, which entities are in the
same position.
ID Position
1 {2,3}
5 {6,2}
12 {2,3}
54 {4,4}
92 {6,2}
I need to get a vector of vectors consisting of keys, which have equal values.
Output for the example input data above: {1,12}, {5,92}
I know I can copy the 2D positions to vector to vectors and loop the first level vector to find indexes of equal second level vectors. Then work back to find keys by selecting the vectors by index and looping again to find the corresponding keys.
Please suggest a cleaner approach for this.
The point of an std::map is to provide an efficient key to value mapping. What you need is an additional value to key mapping - that can be achieved in multiple ways:
Have with an extra std::map that goes from Position to std::vector<ID>.
Use some sort of spatial partitioning data structure (e.g. quadtree, spatial hash, grid) that makes it efficient to find entities depending on their position.
Use a bidirectional multi-map like boost::bimap. This will allow you to have a bidirectional mapping over collection of values without having to use multiple data structures.
"How do I choose?"
It depends on your priorities. If you want maximum performance, you should try all the approaches (maybe using some sort of templatized wrapper) and profile. If you want elegance/cleanliness, boost::bimap seems to be the most appropriate solution.
You could put your data from the map into a std::mutlimap, with the Position as key and ID as value.
As a side note I wonder if a std::pair might be better than a vector for 2d points.
This answer seems to be best, but I'll offer my code anyway.
Given
#include <iostream>
#include <map>
#include <vector>
// Some definiton of Vector2D
struct Vector2D { int x; int y; };
// and some definition of operator< on Vector2D
bool operator<(Vector2D const & a, Vector2D const & b) noexcept {
if (a.x < b.x) return true;
if (a.x > b.x) return false;
return a.y < b.y;
}
How about:
template <typename M>
auto calculate(M const & inputMap) -> std::vector<std::vector<typename M::key_type> > {
std::map<typename M::mapped_type,
std::vector<typename M::key_type> > resultMap;
for (auto const & vp : inputMap)
resultMap[vp.second].push_back(vp.first);
std::vector<std::vector<typename M::key_type> > result;
for (auto & vp: resultMap)
if (vp.second.size() > 1)
result.emplace_back(std::move(vp.second));
return result;
}
Here's how to test:
int main() {
std::map<int, Vector2D> input{
{1, Vector2D{2,3}},
{5, Vector2D{6,2}},
{13, Vector2D{2,3}},
{54, Vector2D{4,4}},
{92, Vector2D{6,2}}
};
auto const result = calculate(input);
// Ugly print
std::cout << '{';
static auto const maybePrintComma =
[](bool & print) {
if (print) {
std::cout << ", ";
} else {
print = true;
}
};
bool comma = false;
for (auto const & v: result) {
maybePrintComma(comma);
std::cout << '{';
bool comma2 = false;
for (auto const & v2: v) {
maybePrintComma(comma2);
std::cout << v2;
}
std::cout << '}';
}
std::cout << '}' << std::endl;
}
You need to provide a reverse mapping. There are a number of ways to do this, including multimap, but a simple approach if your mapping isn't modified after creation is to iterate over the map and build up the reverse mapping. In the reverse mapping, you map value -> list of keys.
The code below uses std::unordered_map to map std::pair<int, int> (the value in the original map) to std::vector<int> (list of keys in the original map). The building of the reverse map is simple and concise:
std::unordered_map<Point, std::vector<int>, hash> r;
for (const auto& item : m) {
r[item.second].push_back(item.first);
}
(See the full example for the definition of hash).
There's no need to worry about whether the key exists; it will be created (and the vector of ids will be initialised as an empty vector) when you attempt to access that key using the r[key] notation.
This solution targets simplicity; it's a workable solution if you need to do this and don't care about performance, memory usage or using third-party libraries like Boost.
If you do care about any of those things, or you're modifying the map while doing lookups in both directions, you should probably explore other options.
Live example
#include <iostream>
#include <map>
#include <unordered_map>
#include <vector>
// Define a point type. Use pair<int, int> for simplicity.
using Point = std::pair<int, int>;
// Define a hash function for our point type:
struct hash {
std::size_t operator()(const Point& p) const
{
std::size_t h1 = std::hash<int>{}(p.first);
std::size_t h2 = std::hash<int>{}(p.second);
return h1 ^ (h2 << 1);
}
};
int main() {
// The original forward mapping:
std::map<int, Point> m = {
{1, {2, 3}},
{5, {6, 2}},
{12, {2, 3}},
{54, {4, 4}},
{92, {6, 2}}
};
// Build reverse mapping:
std::unordered_map<Point, std::vector<int>, hash> r;
for (const auto& item : m) {
r[item.second].push_back(item.first);
}
// DEMO: Show all indices for {6, 2}:
Point val1 = {6, 2};
for (const auto& id : r[val1]) {
std::cout << id << " ";
}
std::cout << "\n";
// DEMO: Show all indices for {2, 3}:
Point val2 = {2, 3};
for (const auto& id : r[val2]) {
std::cout << id << " ";
}
std::cout << "\n";
}

C++ Performing mapping between vectors and unique numbers and vice versa

I need to create a dictionary data structure which maps vector to unique numbers and vice versa:
For example for mapping vectors to unique numbers, I can do the following:
vector ---------> unique number
(0,7,8) 0
(0,8,10) 1
(1,2,9) 2
(1,2,10) 3
(1,3,1) 4
Then I need to map back unique numbers to vectors, e.g. given below:
unique numbers --------> vector
0 (0,7,8)
1 (0,8,10)
2 (1,2,9)
3 (1,2,10)
4 (1,3,1)
I tried to do this mapping by creating a structure of integers and vectors -- however, this turned to be very inefficient. Is there some c++ data structure which can perform the forward and reverse mapping efficiently.
boost::bimap has the same functionality as what you're describing.
It is similar to std::map, but allows either element of the pair to be a key to the other element.
There is Boost.Bimap. This is a related question to Bimap Is there a Boost.Bimap alternative in c++11? .
In short, you can have two maps, one for each relationship (id -> vec, vec -> id).
[example as requested in a comment under the question]
Summarily, this makes the array index in the sorted ordering the "unique number" identifying a specific vector<int>, and seeks a specific vector<int> using std::lower_bound. Effectively, get_vec_id is just a convenience function if you find dealing in vector indices (with (size_t)-1 being a "not-found" sentinel value) more intuitive than repeatedly using lower_bound directly and dealing with iterators.
This is not very convenient when you have insert and/or erase of vector<int>s interspersed with lookups, because 1) earlier-retrieved indices are all invalidated, and 2) inserting and erasing in vectors is O(n). But, it's pretty good when the data's prepared first then a multitude of lookups are done.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
template <typename Data>
size_t get_vec_id(const Data& data, const typename Data::value_type& value)
{
auto it = std::lower_bound(data.begin(), data.end(), value);
if (it != data.end() && *it == value)
return it - data.begin();
else
return (size_t)-1;
}
int main()
{
std::vector<std::vector<int>> data =
{ { 0,7,8 },
{ 0,8,10 },
{ 1,2,9 },
{ 1,2,10 },
{ 1,3,1 } };
std::cout << get_vec_id(data, {0, 7}) << '\n';
std::cout << get_vec_id(data, {0, 7, 8}) << '\n';
std::cout << get_vec_id(data, {0, 7, 9}) << '\n';
std::cout << get_vec_id(data, {1, 2, 9}) << '\n';
std::cout << get_vec_id(data, {1, 2, 11}) << '\n';
std::cout << get_vec_id(data, {1, 3, 1}) << '\n';
std::cout << get_vec_id(data, {1, 4, 1}) << '\n';
// to map from a "vec_id" to a vector, use data[vec_id]...
}

Iterating over more than one seq. container in C++11

I need a piece of advice for the following situation - I can't figure it out for hours:
How to walk through more than one seq . containers of same size (here: two vectors) in a simple way?
int main() {
int size = 3;
std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };
// old-fashioned - ok
for (int i = 0; i < size; i++) {
std::cout << v1[i] << " " << v2[i] << std::endl;
}
// would like to do the same as above with auto range-for loop
// something like this - which would be fine for ONE vector.
// But this does not work. Do I need a hand-made iterator instead?
for (const auto& i:v1,v2) {
std::cout << i << " " << i << std::endl;
}
return EXIT_SUCCESS;
}
Thank you!
There is boost::combine() in Boost.Range that allows one to write
#include <iostream>
#include <iterator>
#include <vector>
#include <boost/range/combine.hpp>
int main()
{
std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };
for (auto&& t : boost::combine(v1, v2))
std::cout << t.get<0>() << " " << t.get<1>() << "\n";
}
Live Example.
If you don't like to rely on this, you can spell out the combine() functionality yourself with Boost.Iterator's zip_iterator and Boost.Range's iterator_range and a little bit of C++14 deduced return-types:
template<class... Ranges>
auto combine(Ranges const&... ranges)
// add -> decltype( boost::make_iterator_range(...) ) in C++11
{
return boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(begin(ranges)...)),
boost::make_zip_iterator(boost::make_tuple(end(ranges)...))
);
}
Live Example.
Explanation: boost::make_zip_iterator creates a boost::tuple of iterators into your input ranges, and overloads all the usual operator++ and operator* that you know and love from regular iterators. The iterator_range then wraps two of these zip_iterators into a package with a begin() and end() function that allows it to be used by the C++11 range-for loop. It generalizes to more than two input ranges as well. You can unpack the K-th element from a tuple with the .get<K> member function.
The range-based for loop was designed as a convenience for iterating one range, because it's by far the most common case. If you need to iterate multiple ranges, which is not that most common case, you can still do it the traditional way:
for (auto i1 = begin(v1), i2 = begin(v2), e = end(v1); i1 != e; ++i1, ++i2)
{
// processing
}

Merging two lists efficiently with limited bound

I am trying to merge two arrays/lists where each element of the array has to be compared. If there is an identical element in both of them I increase their total occurrence by one. The arrays are both 2D, where each element has a counter for its occurrence. I know both of these arrays can be compared with a double for loop in O(n^2), however I am limited by a bound of O(nlogn). The final array will have all of the elements from both lists with their increased counters if there are more than one occurrence
Array A[][] = [[8,1],[5,1]]
Array B[][] = [[2,1],[8,1]]
After the merge is complete I should get an array like so
Array C[][] = [[2,1],[8,2],[8,2],[5,1]]
The arrangement of the elements does not have to be necessary.
From readings, Mergesort takes O(nlogn) to merge two lists however I am currently at a roadblock with my bound problem. Any pseudo code visual would be appreciated.
I quite like Stepanov's Efficient Programming although they are rather slow. In sessions 6 and 7 (if I recall correctly) he discusses the algorithms add_to_counter() and reduce_counter(). Both algorithms are entirely trivial, of course, but can be used to implement a non-recursive merge-sort without too much effort. The only possibly non-obvious insight is that the combining operation can reduce the two elements into a sequence rather than just one element. To do the operations in-place you'd actually store iterators (i.e., pointers in case of arrays) using a suitable class to represent a partial view of an array.
I haven't watched the sessions beyond session 7 (and actually not even the complete session 7, yet) but I would fully expect that he actually presents how to use the counter produced in session 7 to implement, e.g., merge-sort. Of course, the run-time complexity of merge-sort is O(n ln n) and, when using the counter approach it will use O(ln n) auxiliary space.
A simple algorithm that requires twice as much memory would be to order both inputs (O(n log n)) and then sequentially pick the elements from the head of both lists and do the merge (O(n)). The overall cost would be O(n log n) with O(n) extra memory (additional size of the smallest of both inputs)
Here's my algorithm based on bucket counting
time complexity: O(n)
memory complexity: O(max), where max is the maximum element in the arrays
Output:
[8,2][5,1][2,1][8,2]
Code:
#include <iostream>
#include <vector>
#include <iterator>
int &refreshCount(std::vector<int> &counters, int in) {
if((counters.size() - 1) < in) {
counters.resize(in + 1);
}
return ++counters[in];
}
void copyWithCounts(std::vector<std::pair<int, int> >::iterator it,
std::vector<std::pair<int, int> >::iterator end,
std::vector<int> &counters,
std::vector<std::pair<int, int&> > &result
) {
while(it != end) {
int &count = refreshCount(counters, (*it).first);
std::pair<int, int&> element((*it).first, count);
result.push_back(element);
++it;
}
}
void countingMerge(std::vector<std::pair<int, int> > &array1,
std::vector<std::pair<int, int> > &array2,
std::vector<std::pair<int, int&> > &result) {
auto array1It = array1.begin();
auto array1End = array1.end();
auto array2It = array2.begin();
auto array2End = array2.end();
std::vector<int> counters = {0};
copyWithCounts(array1It, array1End, counters, result);
copyWithCounts(array2It, array2End, counters, result);
}
int main()
{
std::vector<std::pair<int, int> > array1 = {{8, 1}, {5, 1}};
std::vector<std::pair<int, int> > array2 = {{2, 1}, {8, 1}};
std::vector<std::pair<int, int&> > result;
countingMerge(array1, array2, result);
for(auto it = result.begin(); it != result.end(); ++it) {
std::cout << "[" << (*it).first << "," << (*it).second << "] ";
}
return 0;
}
Short explanation:
because you mentioned, that final arrangement is not necessary, I did simple merge (without sort, who asked sort?) with counting, where result contains reference to counters, so no need to walk through the array to update the counters.
You could write an algorithm to merge them by walking both sequences sequentially in order, inserting where appropriate.
I've chosen a (seemingly more apt) datastructure here: std::map<Value, Occurence>:
#include <map>
using namespace std;
using Value = int;
using Occurence = unsigned;
using Histo = map<Value, Occurence>;
If you insist on contiguous storage, boost::flat_map<> should be your friend here (and a drop-in replacement).
The algorithm (tested with your inputs, read comments for explanation):
void MergeInto(Histo& target, Histo const& other)
{
auto left_it = begin(target), left_end = end(target);
auto right_it = begin(other), right_end = end(other);
auto const& cmp = target.value_comp();
while (right_it != right_end)
{
if ((left_it == left_end) || cmp(*right_it, *left_it))
{
// insert at left_it
target.insert(left_it, *right_it);
++right_it; // and carry on
} else if (cmp(*left_it, *right_it))
{
++left_it; // keep left_it first, so increment it
} else
{
// keys match!
left_it->second += right_it->second;
++left_it;
++right_it;
}
}
}
It's really quite straight-forward!
A test program: See it Live On Coliru
#include <iostream>
// for debug output
static inline std::ostream& operator<<(std::ostream& os, Histo::value_type const& v) { return os << "{" << v.first << "," << v.second << "}"; }
static inline std::ostream& operator<<(std::ostream& os, Histo const& v) { for (auto& el : v) os << el << " "; return os; }
//
int main(int argc, char *argv[])
{
Histo A { { 8, 1 }, { 5, 1 } };
Histo B { { 2, 1 }, { 8, 1 } };
std::cout << "A: " << A << "\n";
std::cout << "B: " << B << "\n";
MergeInto(A, B);
std::cout << "merged: " << A << "\n";
}
Printing:
A: {5,1} {8,1}
B: {2,1} {8,1}
merged: {2,1} {5,1} {8,2}
You could shuffle the interface a tiny bit in case you really wanted to merge into a new object (C):
// convenience
Histo Merge(Histo const& left, Histo const& right)
{
auto copy(left);
MergeInto(copy, right);
return copy;
}
Now you can just write
Histo A { { 8, 1 }, { 5, 1 } };
Histo B { { 2, 1 }, { 8, 1 } };
auto C = Merge(A, B);
See that Live on Coliru, too