【问题标题】:erase-remove_if idiom - was anything removed?erase-remove_if 成语 - 有什么东西被删除了吗?
【发布时间】:2017-05-24 21:28:07
【问题描述】:

我正在创建一个 API,用户将调用它来从内部向量中删除项目。他们将传入标准以搜索向量以查找要删除的元素。如果找到并删除了任何元素,我希望我的 API 返回一个布尔值。

我打算使用erase-remove idiom 来保持简单和高效。我没有看到一种明显的方法来检测项目实际上已被删除?我最好的选择是在删除之前存储向量中的元素数量并比较值吗?

这里有一些关于这个习语的(未经测试的)示例代码:

std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

boolean removeMultiples(int multiple) {
    v.erase( std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;}), v.end() );
    // return true if anything was removed
}

【问题讨论】:

  • 比较前后大小?

标签: c++ algorithm function vector erase-remove-idiom


【解决方案1】:

一种想法是存储std::remove_if 的返回值,并在执行erase 之前将其与容器end() 迭代器进行比较,如下所示:

bool removeMultiples(int multiple)
{
    auto it = std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;});
    bool any_change = it != v.end();
    v.erase(it, v.end());
    return any_change;
}

【讨论】:

  • 我会采用 lambda 而不是硬编码。然后让删除倍数调用它。
  • @Yakk,你的意思是remove_if 谓词吗?如果是这样,你是对的,它可能应该是一个在容器类型和谓词上参数化的模板,但我只是想在问题上下文中回答。
【解决方案2】:

无需将算法写在一行中。例如你可以写

bool removeMultiples( int multiple )
{
    bool success;

    auto it = std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;});

    if ( ( success = it != v.end() ) ) v.erase( it, v.end() );

    return success;
}

【讨论】:

    【解决方案3】:
    template<class C, class F>
    bool remove_some(C&c, F&&f){
      using std::begin; using std::end;
      auto it = std::remove_if(begin(c), end(c), std::forward<F>(f) );
      bool r = it!=end(c);
      c.erase(it, end(c));
      return r;
    }
    

    然后

    bool removeMultiples(std::vector<int>& f, int multiple) {
      return remove_some(v, [multiple](int i){return !(i%multiple);});
    }
    

    简单干净。

    【讨论】:

      猜你喜欢
      • 2016-12-25
      • 2011-06-02
      • 2017-10-23
      • 2011-07-29
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多