Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient way to filter out elements from std::vector

I have ended up to following code in order to filter out some bad elements from an std::vector:

#include <iostream>
#include <vector>
#include <algorithm>

typedef struct mystruct {
    int id;
    std::string name;
};

int main()
{        
    std::vector<mystruct> all_items = {{151, "test1"}, {154, "test4"}, {152, "test2"}, {151, "test1"}, {151, "test1"}, {153, "test3"}};
    std::vector<int> bad_ids = {151, 152};
    std::vector<mystruct> filter_items;

    for (const auto& item : all_items) {
        if ( std::find(bad_ids.begin(), bad_ids.end(), item.id) != bad_ids.end() ) {
            std::cout << "id: " << item.id << " is bad" << std::endl;
        } else {
            std::cout << "id: " << item.id << " is good item" << std::endl;
            filter_items.emplace_back(item);
        }
    }

    for (auto f : filter_items) {
        std::cout << "Good item: " << f.id << std::endl;
    }
}

Is there any more efficient way? Can the std::remove_copy_if or Boost be used here and how?

like image 953
georgeliatsos Avatar asked Sep 15 '17 09:09

georgeliatsos


1 Answers

Yes you can use std::remove_copy_if, e.g.

std::remove_copy_if(
  all_items.begin(), 
  all_items.end(), 
  std::back_inserter(filter_items),
  [&bad_ids](const mystruct& item) { return std::find(bad_ids.begin(), bad_ids.end(), item.id) != bad_ids.end(); });

LIVE

Or you can use std::remove_if and erase the bad elements on the vector directly, e.g.

all_items.erase(
  std::remove_if(
    all_items.begin(), 
    all_items.end(), 
    [&bad_ids](const mystruct& item) { return std::find(bad_ids.begin(), bad_ids.end(), item.id) != bad_ids.end(); }), 
  all_items.end());

LIVE

like image 80
songyuanyao Avatar answered Sep 22 '22 03:09

songyuanyao