【问题标题】:erasing from vector after remove_if, with reverse iterators: rbegin(), rend()在 remove_if 之后从向量中擦除,使用反向迭代器:rbegin()、rend()
【发布时间】:2021-07-03 23:25:33
【问题描述】:

考虑以下向量:

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

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

{20, 37, 11, 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?

【问题讨论】:

    标签: c++ algorithm vector stdvector


    【解决方案1】:

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

    使用仿函数的代码

    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;
    }
    

    使用 lambda 的代码

    int main() {
      std::vector<int> arr = {20, 37, 11, 20, 15};
      std::map<int, int> seen_values;
      arr.erase(
        std::remove_if(
          arr.begin(), arr.end(), [&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;
    }
    

    两者的输出相同

    20 37 11 15
    

    关于 std::remove_if 的说明

    “剩下的垃圾”实际上是在最后。 std::remove_if 将迭代器返回到要开始删除的第一个位置。

    【讨论】:

    • return ++seen_values[x] &gt; 1;auto&amp; count = seen_values[x]; ++count; return count &gt; 1; 避免查找两次。
    猜你喜欢
    • 2021-01-02
    • 1970-01-01
    • 2013-02-09
    • 2017-06-26
    • 2023-03-26
    • 2020-03-30
    • 2014-10-23
    • 1970-01-01
    相关资源
    最近更新 更多