ome*_*sbk 11 c++ erase-remove-idiom
让我说我有std::vector<std::pair<int,Direction>>.
我试图使用erase-remove_if成语从向量中删除对.
stopPoints.erase(std::remove_if(stopPoints.begin(),
stopPoints.end(),
[&](const stopPointPair stopPoint)-> bool { return stopPoint.first == 4; }));
Run Code Online (Sandbox Code Playgroud)
我想删除所有将.first值设置为4的对.
在我的例子中,我有成对:
- 4, Up
- 4, Down
- 2, Up
- 6, Up
Run Code Online (Sandbox Code Playgroud)
但是,在执行erase-remove_if后,我留下:
- 2, Up
- 6, Up
- 6, Up
Run Code Online (Sandbox Code Playgroud)
我在这做错了什么?
Vit*_*meo 22
正确的代码是:
stopPoints.erase(std::remove_if(stopPoints.begin(),
stopPoints.end(),
[&](const stopPointPair stopPoint)-> bool
{ return stopPoint.first == 4; }),
stopPoints.end());
Run Code Online (Sandbox Code Playgroud)
您需要删除从返回的迭代器开始std::remove_if到矢量末尾的范围,而不仅仅是单个元素.
"为什么?"
std::remove_if在向量内部交换元素,以便将与谓词不匹配的所有元素放到容器的开头.
然后它返回指向第一个谓词匹配元素的迭代器.
std::vector::erase需要擦除从返回的迭代器开始到向量末尾的范围,以便删除与谓词匹配的所有元素.
更多信息: 擦除删除成语(维基百科).
该方法std::vector::erase有两个重载:
iterator erase( const_iterator pos );
iterator erase( const_iterator first, const_iterator last );
Run Code Online (Sandbox Code Playgroud)
第一个只删除元素,pos而第二个删除范围[first, last).
由于您last在调用中忘记了迭代器,因此第一个版本是通过重载分辨率选择的,并且您只删除第一个移位到最后的对std::remove_if.你需要这样做:
stopPoints.erase(std::remove_if(stopPoints.begin(),
stopPoints.end(),
[&](const stopPointPair stopPoint)-> bool { return stopPoint.first == 4; }),
stopPoints.end());
Run Code Online (Sandbox Code Playgroud)
该擦除,删除成语工作原理如下:假设你有一个载体{2, 4, 3, 6, 4},你要删除的4:
std::vector<int> vec{2, 4, 3, 6, 4};
auto it = std::remove(vec.begin(), vec.end(), 4);
Run Code Online (Sandbox Code Playgroud)
{2, 3, 6, A, B}通过将"已移除"值放在最后来转换向量(值A和B结尾都未指定(就像移动了值一样),这就是为什么你得到6了你的例子)并返回一个迭代器A(第一个)被"删除"的价值).
如果你这样做:
vec.erase(it)
Run Code Online (Sandbox Code Playgroud)
std::vector::erase选择第一个重载,你只删除at的值it,即Aget和get {2, 3, 6, B}.
通过添加第二个参数:
vec.erase(it, vec.end())
Run Code Online (Sandbox Code Playgroud)
第二过载被选择,并且你之间擦除值it和vec.end(),这样既A和B被擦除.
我知道在提出这个问题时没有 C++20,所以只需添加这个问题的完整性答案和最新答案,C++20 现在使用std具有更清晰和更简洁的模式::erase_if。
请参阅通用代码示例:
#include <vector>
int main()
{
std::vector<char> cnt(10);
std::iota(cnt.begin(), cnt.end(), '0');
auto erased = std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
std::cout << erased << " even numbers were erased.\n";
}
Run Code Online (Sandbox Code Playgroud)
具体问题代码片段:
std::erase_if(stopPoints, [&](const stopPointPair stopPoint)-> bool {
return stopPoint.first == 4;
});
Run Code Online (Sandbox Code Playgroud)
请在此处查看完整的详细信息:
https ://en.cppreference.com/w/cpp/container/vector/erase2
| 归档时间: |
|
| 查看次数: |
7589 次 |
| 最近记录: |