std :: remove_if -lambda,不从集合中删除任何东西
-
11-10-2019 - |
题
好的,我希望我在这里犯了一个愚蠢的错误。我有一个displayDevice3D的列表,每个displayDevice3D包含displayMode3d的列表。我想从没有任何displayMode3d的displayDevice3D列表中删除所有项目。我正在尝试使用lambda做到这一点,即:
// If the device doesn't have any modes, remove it.
std::remove_if(MyDisplayDevices.begin(), MyDisplayDevices.end(),
[](DisplayDevice3d& device)
{
return device.Modes.size() == 0;
}
);
即使在MyDisplaydevices中的6个displayMode3d中,只有1个在其模式集合中包含任何displayMode3d,但从列表中删除了任何内容。
我在这里犯了什么数字错误?
编辑:
啊,我的错误是我应该使用myDisplayDevices.remove_if而不是std :: remove_if,但是以下答案是正确使用std :: remove_if:p。
MyDisplayDevices.remove_if( [](DisplayDevice3d const & device)
{
return device.Modes.size() == 0;
});
解决方案
您需要在从remove_if返回的迭代器上调用擦除,它应该看起来像这样:
auto new_end = std::remove_if(MyDisplayDevices.begin(), MyDisplayDevices.end(),
[](const DisplayDevice3d& device)
{ return device.Modes.size() == 0; });
MyDisplayDevices.erase(new_end, MyDisplayDevices.end());
其他提示
remove_if
不会从列表中删除任何内容,只是将它们移至结束。您需要与它一起使用 erase
. 。看到这个 问题 更多细节。
正如其他人提到的那样,有多种方法可以使其起作用。但是我的建议是完全避免 remove_if
并坚持基于标准的迭代拆卸。下面的成语都适用于 list
和 vector
并且不会产生意外的行为。
for( vector<TYPE>::iterator iter = vec.begin() ; iter != vec.end() ; )
if( iter->shouldRemove )
iter = vec.erase( iter ) ; // advances iter
else
++iter ; // don't remove
正如下面提到的那样,此方法的成本确实高于 remove_if
当删除超过1个元素时。
remove_if
通过从矢量进一步的进一步复制元素以及应从其前面的矢量中删除的元素来进行作品。例如:remove_if在向量上调用以删除所有0个元素:
0 1 1 0 1 0
结果是:
1 1 1 0 1 0
请注意,矢量尚不正确。那是因为 remove_if
将迭代器返回到最后一个有效元素...它不会自动调整向量大小。您仍然需要打电话 v.erase()
在迭代器上,从您的电话返回 remove_if
.
一个例子如下
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
void print( vector<int> &v )
{
for( int i : v )
printf( "%d ", i );
puts("");
}
int main()
{
vector<int> v = { 0, 1, 1, 0, 1, 0 };
print( v ); // 0 1 1 0 1 0
vector<int>::iterator it = remove_if( v.begin(), v.end(), [](int i){ return i == 0; } );
print( v ); // 1 1 1 0 1 0
v.erase( it, v.end() ); // actually cut out values not wanted in vector
print( v ); // 1 1 1 (correct)
}