std::remove_if
在 C++ 中是一个算法,用于从序列中移除满足特定条件的元素。它并不实际删除容器中的元素,而是将不被移除的元素移到序列的开始处,并返回一个指向新序列末尾的迭代器。被“移除”元素仍然存在于容器中,但是它们之后的元素都是未指定的值【10†source】。
这个算法接受两个迭代器,表示要处理的元素范围,以及一个一元谓词,当一元谓词对元素求值为真时,该元素就会被移除。例如,如果有一个由整数构成的向量,你想移除所有的负数,你可以定义一个一元谓词,当整数为负时返回真【9†source】。
使用 std::remove_if
时,它将对每个元素应用一元谓词,确切地来说,这个过程会涉及到对序列中每个元素做一次谓词的应用【11†source】。
一个典型的使用 std::remove_if
的例子是,当你有一个字符串,并想移除所有空格。你可以使用 std::remove_if
来逻辑上移除所有空格字符,然后使用字符串的 erase
方法来物理上删除那些元素,这个过程被称为“擦除-移除惯用法”【12†source】【14†source】。
下面是一个具体的实现示例,它展示了如何移除一个字符串中的所有空格【14†source】:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string str1{"Text with some spaces"};
auto noSpaceEnd = std::remove(str1.begin(), str1.end(), ' ');
std::cout << std::string_view(str1.begin(), noSpaceEnd) << " size: " << str1.size() << '\n';
str1.erase(noSpaceEnd, str1.end());
std::cout << str1 << " size: " << str1.size() << '\n';
std::string str2 = "Text\n with\t some \t whitespaces\n\n";
str2.erase(std::remove_if(str2.begin(),
str2.end(),
[](unsigned char x) { return std::isspace(x); }),
str2.end());
std::cout << str2 << '\n';
}
输出将会是:
Textwithsomespaces size: 23
Textwithsomespaces size: 18
Textwithsomewhitespaces
c.erase(std::remove_if(t.begin(),t.end(),lambda判断函数),e):可实现将t中满足条件的元素全部删掉
trimmers_.erase(
std::remove_if(trimmers_.begin(), trimmers_.end(),
[](std::unique_ptr<PoseGraphTrimmer>& trimmer) {
return trimmer->IsFinished();
}),
trimmers_.end());
remove_if的参数是迭代器,前两个参数表示迭代的起始位置和这个起始位置所对应的停止位置。
最后一个参数:传入一个回调函数,如果回调函数返回为真,则将当前所指向的参数移到尾部。
返回值是 被移动区域的首个元素 【!!!意味着:先将所有满足条件的成员依次挪到尾部,再返回移动区域的首个元素地址】。
remove_if在头文件algorithm中,故要使用此函数,需添加#include
由于remove_if函数的参数是迭代器,通过迭代器无法得到容器本身,
而要删除容器内的元素必须通过容器的成员函数来进行。
因而此函数无法真正删除元素,只能把要删除的元素移到容器末尾并返回要被删除元素的迭代器,
然后通过erase成员函数来真正删除。因为一般remove_if和erase函数是成对出现的。
void nms(std::vector<Detection>& detections, float nms_thresh = 0.4) {
std::sort(detections.begin(), detections.end(), cmp);
std::vector<bool> toDelete(detections.size(), false);
for (size_t i = 0; i < detections.size(); ++i) {
if (toDelete[i]) continue; // 如果当前元素已被标记为删除,则跳过
for (size_t j = i + 1; j < detections.size(); ++j) {
if (iou(detections[i].bbox, detections[j].bbox) > nms_thresh) {
toDelete[j] = true; // 标记为删除
}
}
}
// 使用擦除-移除惯用法一次性删除所有标记为删除的元素
auto newEnd = std::remove_if(
detections.begin(), detections.end(),
[&toDelete](const Detection& det, size_t idx) { return toDelete[idx]; }
);
detections.erase(newEnd, detections.end()); // 实际删除元素
}