Najlepszym sposobem, aby in situ usunąć element

głosy
2

Mam zestaw obiektów, które iterację, jednak mogę zdecydować podczas iteracji, że jeden (lub więcej) z tych przedmiotów muszą teraz zostać usunięty.

Mój kod wygląda następująco:

if( ! m_Container.empty() )
    {
        for(  typedefedcontainer::iterator it = m_Container.begin();
              it != m_Container.end(); 
              ++it  )
        {
            if( ! ( SomeFunction( (*it), test, TEST!, false ))  )
            {
            // If function returns false, delete object.
                m_Container.erase( it );
                AsyncResponseStore::iterator it = m_asyncResponses.begin();
            }

        }


    }

Ale oczywiście, kiedy usunąć obiekt pojawia się błąd: „Mapa / zestaw iterator nie incrementable”. Czy ktoś może zaproponować lepszy sposób to zrobić?

Zobacz: Co się stanie, jeśli wywołanie erase () na elemencie mapy podczas iteracji od zaczynają się skończy?

Utwórz 09/12/2008 o 17:09
źródło użytkownik
W innych językach...                            


3 odpowiedzi

głosy
6

Jeśli pojemnik obsługuje go (co podejrzewam twój nie robi, ale tytuł pytanie jest nazwą rodzajową więc może to być przydatne dla innych, jeśli nie ty):

struct SomePredicate {
    bool operator()(typedefedcontainer::value_type thing) {
        return ! SomeFunction(thing, "test", "TEST", false);
    }
};

typedefedcontainer::iterator it;
it = std::remove_if(m_Container.begin(), m_Container.end(), SomePredicate());
m_Container.erase(it, m_Container.end());

m_Container musi mieć zakres sposobu usuwania, które obejmuje dowolną sekwencję lub asocjacyjne pojemnika. To musi mieć zmienny iterator, choć i po prostu zauważyłem, że pierwotnie błędnie zinterpretować komunikat o błędzie: mówi „mapa / set iterator nie incrementable”. Więc myślę, że Twój zbiornik jest mapa lub zestaw.

Należy zauważyć, że trzy ostatnie może być fenomenalnym jedno-liner, ale ten margines jest zbyt wąski, żeby go zawierać.

Również, że SomePredicate może mieć konstruktor z parametrami do przechowywania dodatkowych parametrów do someFunction, ponieważ w prawdziwym życiu myślę, że jesteśmy nie stała.

Można rzeczywiście pozbyć SomePredicate całkowicie jeśli używasz doładowania: wiążą się skonstruować funktora. Twój jeden-liner będzie wówczas naprawdę ogromny.

[Edit: Rob Walker słusznie zauważa w swej odpowiedzi założenie, że robię tutaj i że pytanie nie stan, który jest to, że wszystko kasowanie można odłożyć do czasu po iterate-and-test jest wykonywany. Jeśli SomeFunction dostęp m_Container przez ukrytą trasy (np globalnym, albo dlatego SomeFunction jest rzeczywiście funkcja członkiem tego), a jego wyniki zależą od zawartości pojemnika, a następnie mój kod nie może być równoznaczne z kodem pytający użytkownika. Ale myślę, że mój kod jest „chyba nie ma powodu, aby nie” default].

Odpowiedział 09/12/2008 o 17:39
źródło użytkownik

głosy
6

To zależy od pojemnika. Lista kontener obsługuje usunięcie podczas wyliczania wracając nową iterację z metody kasowania, który reprezentuje następną pozycję na liście. mapa nie obsługuje tej funkcji.

Prosta metoda na mapie jest zgromadzić elementy, które mają zostać skasowane w oddzielnej liście, a następnie iteracyjne nad tej listy po zakończeniu przetwarzania mapę, aby usunąć elementy z mapy. Zakłada się, że można odroczyć do czasu usunięcia iteracji została zakończona. Jeśli nie, to nie masz wyboru, ale restart iteracji dla każdego usunięcia.

Odpowiedział 09/12/2008 o 17:18
źródło użytkownik

głosy
0

Poprawiono brzmienie:

for(  typedefedcontainer::iterator it = m_Container.begin();
      it != m_Container.end(); 
        )
{
    if( ! ( SomeFunction( (*it), "test", "TEST!", false ))  )
    {
    // If function returns false, delete object.
        m_Container.erase( it++ );
    }
    else
    { 
        ++i;
    } 

}

Gdy element jest usuwany, wszystkie wskaźniki do niego stać unieważnione. Dlatego używając go ++ mamy wokół niego. Dzięki ci, którzy napisali sugestie.

Odpowiedział 09/12/2008 o 17:30
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more