49

わかりました、私はここでばかげた間違いをしたと思います。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のうち、ModesコレクションにDisplayMode3dが含まれているのは1つだけですが、リストから削除されるものはありません。

私はここでどんな多くの間違いを犯しましたか?

編集:

ああ、私の間違いは、std :: remove_ifの代わりにMyDisplayDevices.remove_ifを使用する必要があるということでしたが、以下の答えはstd :: remove_if:pの使用に対して正しいです。

MyDisplayDevices.remove_if( [](DisplayDevice3d const & device) 
                            { 
                                return device.Modes.size() == 0; 
                            });
4

4 に答える 4

85

remove_ifから返されたイテレータでeraseを呼び出す必要があります。次のようになります。

auto new_end = std::remove_if(MyDisplayDevices.begin(), MyDisplayDevices.end(),
                              [](const DisplayDevice3d& device)
                              { return device.Modes.size() == 0; });

MyDisplayDevices.erase(new_end, MyDisplayDevices.end());
于 2010-12-18T15:27:27.953 に答える
22

remove_ifリストから何も削除せず、最後に移動するだけです。と一緒に使用する必要がありますerase。詳細については、この質問を参照してください。

于 2010-12-18T15:26:24.803 に答える
13

remove_ifサイズ変更は実行しませんが、代わりに、削除されていない最後の要素に続く要素にイテレータを返します。このイテレータを渡してerase()、クリーンアップを行うことができます。

ここに画像の説明を入力してください

于 2016-11-10T08:00:25.543 に答える
1

他の人が述べているように、それを機能させる方法があります。ただし、私のアドバイスは、完全に回避remove_ifし、代わりに標準のイテレータベースの削除に固執することです。以下のイディオムは、との両方で機能listvector、予期しない動作を生成しません。

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)
}
于 2013-05-04T01:22:26.023 に答える