在 remove_if 之后从向量中擦除,使用反向迭代器:rbegin()、rend() 使用函子的代码使用 lambda 的代码两者的输出相同关于 std::remove_if 的注释

问题描述

考虑以下向量:

std::vector<int> arr = {20, 37,11,20,15}

我需要删除重复项,即遇到超过 n 次(在本例中为 n=1) 结果向量应如下所示:

{20,37,15}

即应该删除后面的元素,而不是前面的元素。

我有一个想法,在 std::remove_if 函数中使用 rbegin() 和 rend() 迭代器来开始从末尾删除元素,但是我不确定如何在 remove_if 之后从向量中删除元素完毕。我相信“剩饭剩菜”是一开始就积累起来的:

auto new_end = std::remove_if(arr.rbegin(),arr.rend(),[&n,&arr](const int a) {
    return std::count(arr.begin(),arr.end(),a) > n;
});
//how to erase garbage?

解决方法

传递给 std::remove_if 的函子可以有内存。

使用函子的代码

Product

使用 lambda 的代码

struct remove_duplicates {
  std::map<int,int> seen_values_;
  bool operator()(int x) {
    seen_values_[x]++;
    return seen_values_[x] > 1;
  }
};

int main() {
  std::vector<int> arr = {20,37,11,20,15};
  arr.erase(
    std::remove_if(arr.begin(),arr.end(),remove_duplicates()),arr.end());

  for (int x : arr)
    std::cout << x << " ";
  std::cout << std::endl;
}

两者的输出相同

int main() {
  std::vector<int> arr = {20,15};
  std::map<int,int> seen_values;
  arr.erase(
    std::remove_if(
      arr.begin(),[&seen_values](int x) {
        seen_values[x]++;
        return seen_values[x] > 1;
      }),arr.end());

  for (int x : arr)
    std::cout << x << " ";
  std::cout << std::endl;
}

关于 std::remove_if 的注释

“剩下的垃圾”实际上是在最后。 20 37 11 15 返回一个迭代器到第一个位置开始删除。