std :: vector删除满足某些条件的元素

时间:2013-06-24 08:16:26

标签: c++ vector stl

正如标题所说,我想删除/合并满足特定条件的向量中的对象。我的意思是我知道如何从矢量中删除整数,例如值为99。

Scott Meyers的删除成语:

vector<int> v;
v.erase(remove(v.begin(), v.end(), 99), v.end());

但是假设有一个包含延迟成员变量的对象向量。现在我想要消除延迟差异仅小于特定阈值的所有对象,并希望将它们组合/合并到一个对象。

过程的结果应该是对象的向量,其中所有延迟的差异应该至少是指定的阈值。

3 个答案:

答案 0 :(得分:28)

std::remove_if来救援!

99将替换为UnaryPredicate,它将过滤您的延迟,我将使用lambda函数。

以下是这个例子:

v.erase(std::remove_if(
    v.begin(), v.end(),
    [](const int& x) { 
        return x > 10; // put your condition here
    }), v.end());

答案 1 :(得分:1)

一个老问题但很受欢迎的参考文献,所以我为此添加了另一个选择。

remove_if函数保留序列的顺序。那可能非常重要。但是,如果您的程序不关心顺序,也可能会浪费时间。

为了保留顺序,remove_if需要向下移动元素以填充已删除的元素。

让我介绍一下partition。与其移动元素以填补空白,不如将元素从末端移动到空隙中。这不会保留顺序,但是可以快得多,尤其是在大型阵列中。

这是一个示例程序:

#include <algorithm>
#include <chrono>
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <vector>

using namespace std;

struct Event {
  chrono::nanoseconds delay;
  string name;

  friend ostream &operator<<(ostream &os, const Event &e) {
    return os << "{ \"delay\": " << e.delay.count() << ", \"name\": \""
              << e.name << "\" }";
  }
};

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &container) {
  bool comma = false;
  os << "[ ";
  for (const auto &x : container) {
    if (comma)
      os << ", ";
    os << x;
    comma = true;
  }
  os << " ]";
  return os;
}

int main() {
  vector<Event> iv = {
      {0ms, "e1"},  {10ms, "e2"}, {11ms, "e3"}, {0ms, "e4"},
      {12ms, "e5"}, {8ms, "e6"},  {13ms, "e7"},
  };

  iv.erase(partition(begin(iv), end(iv),
                     [](const auto &x) { return x.delay > 0ns; }),
           end(iv));
  cout << iv << '\n';
  return 0;
}

我用GCC在Linux上编译它,如下所示:
g++ -Wall -W -pedantic -g -O3 -std=c++17 partition-test.cpp -o partition-test

运行它:
./partition-test [ { "delay": 13000000, "name": "e7" }, { "delay": 10000000, "name": "e2" }, { "delay": 11000000, "name": "e3" }, { "delay": 8000000, "name": "e6" }, { "delay": 12000000, "name": "e5" } ]

让我也介绍一个有趣的命令行工具,名为jq,又名JSON查询:

./partition-test | jq 
[
  {
    "delay": 13000000,
    "name": "e7"
  },
  {
    "delay": 10000000,
    "name": "e2"
  },
  {
    "delay": 11000000,
    "name": "e3"
  },
  {
    "delay": 8000000,
    "name": "e6"
  },
  {
    "delay": 12000000,
    "name": "e5"
  }
]

这也是一个很棒的JSON格式化程序。使其易于阅读。

现在您可以看到,“ e7”和“ e6”以延迟== 0填充到已擦除的事件对象中。并且该数组不再按顺序排列。

答案 2 :(得分:0)

使用谓词函数(C ++ 11中的惯用方法):

v.erase(remove_if(
            v.begin(), v.end(), bind(greater<int>(), _1, 99)),
        v.end());