Kadir Erdem Demir
Kadir Erdem Demir

Reputation: 3605

Reducing selective elements of a map of vectors into a vector

I have a legacy code simplified as below:

std::map< int, std::vector<int> > list2D;

given a range( a number range for example between 10 - 90 ) I need need to filter the map first and eliminate the elements which are not between the number range. Again given the elements

20 -> {10,20}, 40 -> {500,200}, 100 -> {1,2,3} given the range is 10-90 I need the filter the one with 100.

Than I need to concatenate all the vectors left. So result will be {10,20,500,200} .

My legacy code was doing that with two for loops. I am planning to use lower_bound function for filtering step. But it seems I will still need a for loop. Simplified version can be seen below. To be honest the version with 2 for loops was looking more simple.

void simplifiedFoo ()
{
  std::vector<int> returnVal;
  std::map<int, std::vector<int> > list2D = {{20 , {10,20} }, 
                                              {40 , {500,200}}, 
                                              {100 , {1, 2, 3}} }; 

  auto itlow=list2D.lower_bound (10);               
  auto itup=list2D.lower_bound (50);                
  if ( itlow != list2D.end() && itup == list2D.end() )// Don't like this if even not sure if it is correct.  
     --itup;

  while ( itlow != itup)  // How to avoid second loop
  {
     returnVal.insert(returnVal.end(), itlow->second.begin(), itlow->second.end());
     ++itlow;
  }
  for ( auto elem : returnVal)
    std::cout << elem << " " ; 

  return 0;
}

What can be the preferable clean way for that(I need to implement this with vs2010)? Is there clean way I can achieve "reduce" functionality in C++ for my case?

Upvotes: 1

Views: 63

Answers (2)

A.S.H
A.S.H

Reputation: 29352

Not sure if this is what you mean, but if you are looking for using "std oneliners", this would work:

  std::for_each(itlow, itup,
      [&returnVal](const auto& elem) {
          returnVal.insert(returnVal.end(), elem.second.begin(), elem.second.end());
      });

Now, can we call this "the preferable clean way for that"? I think it is debatable.

Upvotes: 2

Olaf Dietsche
Olaf Dietsche

Reputation: 74088

I think, you must use upper_bound for the second value, otherwise the upper value will be excluded

auto first = list2D.lower_bound(10);               
auto last = list2D.upper_bound(90);

You don't need to check, if the lower iterator is != end() and the upper one is == end(). So your loop just becomes

for (; first != last; ++first) {
    // ...
}

If the upper iterator were equal to end(), it would be equivalent to

for (; first != list2D.end(); ++first) {
    // ...
}

Upvotes: 1

Related Questions