Using Structured binding declaration in Range-based for loop

3.5k Views Asked by At

I am trying to combine two std::map containers (say std::map<int, int> foo, bar) into a third std::map (say std::map<int, int> foobar).

I know that I can achieve this using iterators as below:

    std::map<int, int>::iterator itr1 = foo.begin();
    std::map<int, int>::iterator itr2 = bar.begin();

    for (; itr1 != foo.end() && itr2 != bar.end(); ++itr1, ++itr2) 
    {
      foobar[itr1->first] += itr1->second;
      foobar[itr2->first] += itr2->second;
    }

But how can I use Range-based for loop (and maybe, in conjunction with Structured binding declaration) to achieve the same?

Or is there any better way to combine these two associative containers?

EDIT: The expected answer to this question should take two containers (std::map here) and combine them into a single union/united map with the keys being from both the respective associative containers and the values of duplicate keys being added.

Example: If given std::map containers foo and bar are:

  std::map<int, int> foo = {{1, 10}, {2, 20}, {3, 30}};
  std::map<int, int> bar = {{3, 50}, {4, 60}};

Then `foobar' should be:

  std::map<int, int> foobar = {{1, 10}, {2, 20}, {3, 80}, {4, 60}};

This all done in a single Range-based for loop.

2

There are 2 best solutions below

0
On

is there any better way to combine these two associative containers?

The easiest way is probably to iterate over them separately:

for(auto[k, v] : foo) foobar[k] += v;
for(auto[k, v] : bar) foobar[k] += v;

If you want to discard any data already in foobar:

foobar = foo;
for(auto[k, v] : bar) foobar[k] += v;
1
On

There's a standard library algorithm for doing just this: std::set_union, in <algorithm>. Now, granted, it's ugly because it users iterator pairs, but you can probably improve that using ranges.

Anyway:

std::set_union(
    foo.begin(), foo.end(), 
    bar.begin(), bar.end(),
    std::inserter(foobar, foobar.begin())
);

should do the trick.


PS - This may be a bit slow - as std::map itself is really slow. I assume you don't care about performance with this map (or it's really smaller), otherwise you shouldn't be using it.