2014-05-01 22 views
6

Mam , z której chcę erase-remove elementów pasujących do pewnego predykatu. Usunięte obiekty powinny mieć wywoływaną metodę, która ustawia jakiś status do użycia w innym miejscu.Usuń elementy z wektora i zmodyfikuj te, które zostały usunięte.

Czy istnieje powód, dla którego nie powinienem tego robić w funkcji predykatu, gdy zwracana jest wartość true? Czuję się trochę jak mieszanie obaw, ale jedyne alternatywy, o których myślę, wydają się dużo brzydsze.

+0

Byłoby lepiej, aby podsumować alternatywy, albo masz zamiar dostać je za odpowiedzi. – djechlin

+0

Tak właśnie bym to zrobił, ale co mogę powiedzieć, jestem leniwy. Nie ma alternatywy, która nadal pozwala na korzystanie z biblioteki 'algorithm', prawda? Tak czy owak, łamiecie pojęcie "doskonałych" standardów programowania. (Edycja: podobno jest, ale nadal byłbym kuszony, aby zrobić to po swojemu!) – Elliott

+0

To jest najbardziej efektywny sposób, jaki mogę wymyślić. – 101010

Odpowiedz

7

Istnieją dwa powody, dla których prawdopodobnie nie jest to dobry pomysł.

Po pierwsze, większość standardowych algorytmów bibliotecznych nie powinna używać predykatów, które modyfikują elementy, na których działają.

Po drugie, std::remove i std::remove_if nie dają dobrego zestawu "usuniętych" elementów *. Możesz polegać tylko na elementach wybranych do zachowania. Elementy "usunięte" mogą w rzeczywistości być kopiami "dobrych". A ponieważ przechowujesz wspólne wskaźniki, mogą one wskazywać na te same obiekty, co "dobre" elementy.

Alternatywą byłoby użycie std::partition, następnie iteracja na odpowiedniej sekcji partycji, a następnie użycie erase w sposób podobny do idiomu usuwanie-usuwanie.

auto p = std::partition(v.begin, v.end(), pred); 
std::for_each(p, v.end(), call_method_functor); 
v.erase(p, v.end()); 

* Algorytmy te powinny prawdopodobnie zostały nazwane keep i keep_if

+0

To dobre rozwiązanie, ale tak naprawdę nie rozumiem tej części: "' std :: remove' ... nie daje dobrego zestawu "usuniętych elementów". Dlaczego ma to znaczenie, jeśli wywołujesz jedyną potrzebną funkcję na obiekcie, zanim funkcja predykatu wróci? – Elliott

+0

@ Elliott - Napisałem kod, który próbował użyć "usuniętych" elementów, a ja całkiem się spaliłem. Podsumowując, nie powinieneś używać usuniętych elementów, z wyjątkiem usuwania. Rozwiązaniem jest dokładnie to, co juanchopanza umieścił w swojej odpowiedzi, 'std :: partition' (lub' std :: stable_partition'). – PaulMcKenzie

+1

Podoba mi się twój pomysł używania 'partycji', ale część dotycząca' remove (_if) 'nie daje żadnych gwarancji co do usuniętych elementów jest prawdopodobnie nieistotna, ponieważ OP stwierdza, że ​​będzie działał na tych obiektach z innego miejsca. – Praetorian

Powiązane problemy