一个老问题,但很受欢迎,所以我要为此添加另一个选项。
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;
}
我在 Linux 上使用 GCC 编译它,如下所示:
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 aka JSON Query:
./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 填充已擦除的 Event 对象。并且数组不再按顺序排列。