【C++】copy_if/remove_copy_if – filter関数の実現【関数型プログラミング】

C++標準ライブラリにはfilter関数が存在しません。代わりに別機能による代替処理を紹介します。

スポンサーリンク

copy_if

copy_ifテンプレート関数は、条件を満たした要素のみをコピーする機能です。これによってfilter関数やselect/find_all/grep関数の実現が可能となります。

// #include <algorithm> // copy_if
// #include <iterator>  // back_inserter
std::vector<int> w, v = {1, 2, 3, 4, 5};

std::copy_if(v.begin(), v.end(), std::back_inserter(w), [](int i) {
   return i < 4;
});

v; // {1, 2, 3, 4, 5}
w; // {1, 2, 3}

第一引数と第二引数にコピー元の要素範囲を指定し、第三引数にコピー先のイテレータを指定します。第四引数にはフィルター用の条件を関数オブジェクトとして指定します。

remove_copy_if

なお、copy_if関数の代わりにremove_copy_ifを利用すると、条件を満たさない要素のみが抽出されます。これによってfilterNot関数やreject関数的な挙動を実現できます。

std::vector<int> w, v = {1, 2, 3, 4, 5};

std::remove_copy_if(v.begin(), v.end(), std::back_inserter(w), [](int i) {
   return i < 4;
}); // w == {4, 5}

filter関数の実現

template<class Container, class Predicate>
Container filter(const Container& c, Predicate f) {
  using std::begin;
  using std::end;
  Container r;
  std::copy_if(begin(c), end(c), std::back_inserter(r), f);
  return r;
}
assert(3 == filter(std::vector<int>{2, 3, 4}, [](int i) { return i < 4; }).back());
assert("abc" == filter(std::string("a::b_c()"), isalpha));

広告