Usuwanie co któryś element z wektora

0

Piszę sobie program, gdzie w jednej części potrzebuje dodawać m-1 zer do wektora po każdym elemencie czyli dla np. m=3 i wektorze składającym się z {1,2,3,4,5,6} powinien być wynik {1,0,0,2,0,0,3,0,0,..} i to wygląda, że działa poprawnie:

        for (auto it = tab.begin() + 1; it < tab.end(); it = it + m) {
            for (j = 1; j < m; j++) {
                it = tab.insert(it, 0);
            }
        {

Natomiast jeśli chciałbym usuwać m-1 elementów po każdym kolejnym elemencie czyli dla np. m=3 i wektorze składającym się z {1,2,3,4,5,6} powinien być wynik {1,4} no i tu coś nie chce działać poprawnie. Niestety nie działa to jak należy i nie mam pomysłu co robię źle.

for (auto ot = tab2.begin(); ot < tab2.end(); ot++) {
            for (j = 0; j < m - 1; j++) {
                ot = tab2.erase(ot + 1);
            }
}

0

Musisz iterować od tyłu do początku.
Jak iterujesz od początku i usuwasz następny element, to iterator nie wie, gdzie jest następny element.

8

Co oznacza "nie chce działać poprawnie"?

Osobiście, zrobiłbym to tak: wziął kod z mojego posta: https://dev.krzaq.cc/post/an-erase-remove-idiom-gotcha/

i usuwał w prosty sposób:

int i{0};
erase_if(tab2, [&i](auto&&){ return i++ % m != 0; });

https://coliru.stacked-crooked.com/a/5c17dca75238d130

0
Spine napisał(a):

Musisz iterować od tyłu do początku.

To nie jest rozwiązanie, bo erase unieważnia iteratory wskazujące na usuwany element i wszystkie następne. Nie ma zatem gwarancji poprawnego działania.

1

using vect = std::vector<int>;

void remove( vect& in , int m )
{
    if( m<=1 ) return;

    vect out;
    out.reserve(in.size()/2);

    for( auto index=0 ; index<in.size() ; index+=m )
    {
        out.push_back(in[index]);
    }

    in = std::move(out);
}

1

Problem polega na tym, że usuwając element wszystkie następne elementy przesuwają się o jeden, więc zmieniają się indeksy. Dlatego twój kod nie działa poprawnie, bo zakłada, że indeksy elementów pozostają bez zmian.
Poza tym usuwanie elementów pojedynczo powoduje dużo niepotrzebnego kopiowania.
To powinno wyglądać tak:

void eraseEveryNtElement(std::vector<int>& v, int n)
{
    auto i = n;
    auto newEnd = std::remove_if(v.begin(), v.end(), [&i, n](auto) {
         if (i == 0) i = n;
         return --i == 0;
    });
    v.erase(newEnd, v.end());
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1