Frage

Ok, ich erwarte, dass ich hier einen stummen Fehler gemacht. Ich habe eine Liste von DisplayDevice3d und jede DisplayDevice3d enthält eine Liste von DisplayMode3d. Ich möchte alle Elemente aus der Liste der DisplayDevice3d entfernen, die nicht DisplayMode3d die haben. Ich versuche, eine Lambda zu verwenden, es zu tun, das heißt:.

    // If the device doesn't have any modes, remove it.

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

Auch wenn von 6 DisplayMode3d ist in MyDisplayDevices, nur 1 jede DisplayMode3d den in seiner Modi Sammlung hat, wird nichts aus der Liste entfernt werden.

Was numpty Fehler habe ich gemacht hier?

Edit:

Ah ok, mein Fehler war ich statt std MyDisplayDevices.remove_if werden sollte :: remove_if, aber die Antworten unten richtig sind für die Verwendung von std :: remove_if: s.

MyDisplayDevices.remove_if( [](DisplayDevice3d const & device) 
                            { 
                                return device.Modes.size() == 0; 
                            });
War es hilfreich?

Lösung

Sie müssen sich auf dem Iterator aus remove_if zurückLösch nennen, es sollte wie folgt aussehen:

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

MyDisplayDevices.erase(new_end, MyDisplayDevices.end());

Andere Tipps

remove_if entfernt nichts aus der Liste es verschiebt sie nur zu beenden. Sie müssen es benutzen zusammen mit erase. Sehen Sie diese Frage für weitere Details.

remove_if führen keine Änderungen der Größe, sondern es gibt nur den Iterator auf das Element, das das letzte Element folgt nicht entfernt. Dieser Iterator kann erase() weitergegeben werden, um die Sanierung zu tun.

 image description hier

eingeben

Wie andere erwähnt haben, gibt es Möglichkeiten, es funktioniert. Allerdings wäre mein Rat vollständig sein, statt remove_if und Stick auf eine Standard-Iterator-basierte Entfernung zu vermeiden. Das Idiom unten funktioniert sowohl für list und vector und produziert nicht unerwartetes Verhalten.

for( vector<TYPE>::iterator iter = vec.begin() ; iter != vec.end() ; )
  if( iter->shouldRemove )
    iter = vec.erase( iter ) ; // advances iter
  else
    ++iter ; // don't remove

Wie die Kommentare unten erwähnt, ist diese Methode hat eine höhere Kosten als remove_if, wenn mehr als 1 Element entfernt wird.

remove_if funktioniert durch Elemente aus weiter nach vorne in dem Vektor Kopieren und Überschreiben von Vektoren, die aus dem Vektor durch eine unmittelbar vor ihm entfernt werden sollen. Zum Beispiel: remove_if auf einem Vektor bezeichnet alle 0 Elemente entfernen:

0 1 1 0 1 0

Ergebnisse in:

1 1 1 0 1 0

Beachten Sie, wie der Vektor ist nicht richtig vor. Das ist, weil remove_if einen Iterator auf das letzte gültige Element zurückgibt ... es nicht automatisch die Vektor-Größe ändern. Sie müssen noch auf Anruf v.erase() auf dem Iterator von Ihrem Anruf remove_if zurückgegeben.

Ein Beispiel ist unter

#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)
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top