std :: remove_if -lambda、コレクションから何も削除しない
-
11-10-2019 - |
質問
わかりました、私はここで愚かな間違いを犯したと思います。 displaydevice3dのリストがあり、各displaydevice3dにはdisplaymode3dのリストが含まれています。 displayMode3Dを持たないDisplayDevice3Dのリストからすべてのアイテムを削除したいと思います。私はそれをするためにラムダを使用しようとしています、すなわち。
// 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のうち、モードコレクションにdisplayMode3Dがあるのは1つだけですが、リストから削除されていません。
私はここでどのような数字の間違いを犯しましたか?
編集:
ああ、私の間違いは、std :: remove_ifの代わりにmydisplaydevices.remove_ifを使用する必要があることでしたが、以下の回答はstd :: remove_if:pの使用に正しいです。
MyDisplayDevices.remove_if( [](DisplayDevice3d const & device)
{
return device.Modes.size() == 0;
});
解決
remove_ifから返されたiteratorで消去を呼び出す必要があります。次のようになります。
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
複数の要素が削除されたとき。
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)
}