std::remove_if în C++

Elimină logic elementele care îndeplinesc o condiție; folosit cu erase sau înlocuit de std::erase_if (C++20).

Sintaxă
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred conditie);

Ce face std::remove_if

std::remove_if funcționează ca std::remove, dar decide cu o funcție ce elemente dispar. Elementele păstrate sunt mutate la început, în ordinea inițială, iar funcția returnează noul sfârșit. Containerul nu se micșorează singur.

Ștergerea reală: v.erase(std::remove_if(v.begin(), v.end(), cond), v.end());. Din C++20 scrii simplu std::erase_if(v, cond), disponibil pentru vector, string, deque, list, dar și pentru map și set, unde remove_if nu se poate folosi.

Parametri

Parametru Descriere
first, last Intervalul.
conditie Funcție care returnează true pentru elementele de eliminat.

Ce returnează

Iterator către noul sfârșit logic al intervalului.

Exemple

Exemplul 1: Eliminarea notelor sub 5 (erase-remove)

#include <algorithm>
#include <print>
#include <vector>

int main() {
    std::vector<int> note{8, 4, 10, 3, 7, 4, 9};

    note.erase(std::remove_if(note.begin(), note.end(), [](int n) { return n < 5; }), note.end());
    std::println("{}", note);
}

Rezultat

[8, 10, 7, 9]

Exemplul 2: Același lucru cu std::erase_if (C++20)

#include <print>
#include <string>
#include <vector>

struct Produs {
    std::string nume;
    int stoc;
};

int main() {
    std::vector<Produs> produse{{"Cafea", 12}, {"Ceai", 0}, {"Zahăr", 5}, {"Miere", 0}};

    auto sterse = std::erase_if(produse, [](const Produs& p) { return p.stoc == 0; });

    std::println("Am scos {} produse epuizate. Rămân:", sterse);
    for (const Produs& p : produse) {
        std::println("  {} ({})", p.nume, p.stoc);
    }
}

Rezultat

Am scos 2 produse epuizate. Rămân:
  Cafea (12)
  Zahăr (5)

Exemplul 3: Varianta ranges

std::ranges::remove_if returnează subintervalul de „gunoi”, pe care îl dai direct lui erase.

#include <algorithm>
#include <cctype>
#include <print>
#include <string>

int main() {
    std::string text = "Ana, are 3 mere!";

    auto gunoi = std::ranges::remove_if(text, [](unsigned char c) { return std::ispunct(c); });
    text.erase(gunoi.begin(), gunoi.end());
    std::println("{}", text);
}

Rezultat

Ana are 3 mere

Greșeli frecvente

  • Uiți erase și vectorul păstrează la final elemente vechi, cu valori nespecificate.
  • Încerci std::remove_if pe un std::map sau std::set: nu compilează, pentru că cheile nu pot fi mutate. Folosește std::erase_if(m, ...).
  • Ștergi elemente din vector cu erase într-o buclă for cu index sau iterator, fără să ajustezi poziția. Sari peste elemente; erase-remove le tratează pe toate dintr-o trecere.

Comenzi înrudite

  • std::remove: Mută la final elementele egale cu o valoare și returnează noul sfârșit; ștergerea reală se face cu erase.
  • std::copy_if: Copiază doar elementele care îndeplinesc o condiție, păstrând ordinea lor.
  • std::partition: Împarte elementele în două grupuri: întâi cele care îndeplinesc condiția, apoi celelalte.
  • std::erase_if: Șterge dintr-un container toate elementele egale cu o valoare (std::erase) sau care îndeplinesc o condiție (std::erase_if).