Espacios de nombres
Variantes
Acciones

std::ranges::remove, std::ranges::remove_if

De cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
Biblioteca de algoritmos
Políticas de ejecución (C++17)
Operaciones de secuencia no modificantes
(C++11)(C++11)(C++11)
(C++17)
Operaciones de secuencia modificantes
Operaciones en almacenamiento no inicializado
Operaciones de partición
Operaciones de ordenación
(C++11)
Operaciones de búsqueda binaria
Operaciones de conjuntos (en rangos ordenados)
Operaciones de pila
(C++11)
Operaciones mínimo/máximo
(C++11)
(C++17)
Permutaciones
Operaciones numéricas
Bibliotecas C
 
Algoritmos restringidos
Operaciones de secuencia no modificantes
Operaciones de secuencia modificantes
Operaciones en almacenamiento sin inicializar
Operaciones de partición
Operaciones de ordenamiento
Operaciones de búsqueda binaria
Operaciones de conjuntos (en rangos ordenados)
Operaciones de montículo/montón
Operaciones de mínimo/máximo
Permutaciones
 
Definido en el archivo de encabezado <algorithm>
Signatura de la llamada
template< std::permutable I, std::sentinel_for<I> S, class T,

          class Proj = std::identity >
requires std::indirect_binary_predicate<ranges::equal_to,
             std::projected<I, Proj>, const T*>
constexpr ranges::subrange<I>

    remove( I first, S last, const T& value, Proj proj = {} );
(1) (desde C++20)
template< ranges::forward_range R, class T, class Proj = std::identity >

requires std::permutable<ranges::iterator_t<R>> &&
         std::indirect_binary_predicate<ranges::equal_to,
             std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::borrowed_subrange_t<R>

    remove( R&& r, const T& value, Proj proj = {} );
(2) (desde C++20)
template< std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,

          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr ranges::subrange<I>

    remove_if( I first, S last, Pred pred, Proj proj = {} );
(3) (desde C++20)
template< ranges::forward_range R, class Proj = std::identity,

          std::indirect_unary_predicate<
              std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>

    remove_if( R&& r, Pred pred, Proj proj = {} );
(4) (desde C++20)

Elimina todos los elementos que satisfacen un criterio específico del rango [firstlast) y devuelve un subrango [retlast), donde ret es un iterador pasado el final para el nuevo final del rango.

1) Elimina todos los elementos que son iguales a value, usando std::invoke(proj, *i) == value para comparar.
3) Elimina todos los elementos para los que std::invoke(pred, std::invoke(proj, *i)) devuelve true.
2,4) Igual que (1,3), pero usa r como el rango, como si usara ranges::begin(r) como first y ranges::end(r) como last.

La eliminación se realiza desplazando (mediante la asignación de movimiento) los elementos del rango de forma que los elementos que no se van a eliminar aparezcan al principio del rango. Se conserva el orden relativo de los elementos que quedan y el tamaño: físico del contenedor no cambia. Los iteradores que apuntan a un elemento entre el nuevo final lógico y el final físico del rango siguen siendo desreferenciables, pero los elementos en sí tienen valores no especificados (según la poscondición de MoveAssignable).

Las entidades similares a funciones descritas en esta página son niebloids, es decir:

En la práctica, pueden implementarse como objetos función o con extensiones de compilador especiales.

Contenido

[editar] Parámetros

first, last - El rango de elementos a procesar.
r - El rango de elementos a procesar.
value - El valor de los elementos a eliminar..
pred - El predicado para aplicar a los elementos proyectados.
proj - La proyección para aplicar a los elementos.

[editar] Valor de retorno

{ret, last}, donde [firstret) es el subrango resultante después de la eliminación, y los elementos en el subrango [retlast) están todos en un estado válido pero no especificado.

[editar] Complejidad

Exactamente N aplicaciones del predicado correspondiente y cualquier proyección, donde N = ranges::distance(first, last), y N - 1 operaciones de movimiento en el peor de los casos.

[editar] Notas

Una llamada a ranges::remove suele ir seguida de una llamada a la función miembro erase de un contenedor, que borra los valores no especificados y reduce el tamaño: físico del contenedor para que coincida con su nuevo tamaño lógico. Estas dos invocaciones juntas constituyen el llamado modismo Erase–remove, que se puede lograr mediante la función libre std::erase que tiene sobrecargas para todos los contenedores estándar de secuencia, o std::erase_if que tiene sobrecargas para todos los contenedores estándar}}.

Las funciones miembro de contenedor de nombre similar, list::remove, list::remove_if, forward_list::remove, y forward_list::remove_if borran los elementos eliminados.

Estos algoritmos no se pueden usar con contenedores asociativos como std::set y std::map porque sus tipos iterador no eliminan la referencia a los tipos MoveAssignable (las claves en estos contenedores no son modificables).

Debido a que std::remove toma value por referencia, puede tener un comportamiento inesperado si es una referencia a un elemento del rango [firstlast).

[editar] Posible implementación

remove
struct remove_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class T,
             class Proj = std::identity>
    requires std::indirect_binary_predicate<
                 ranges::equal_to, std::projected<I, Proj>, const T*>
    constexpr ranges::subrange<I>
        operator()(I first, S last, const T& value, Proj proj = {}) const
    {
        first = ranges::find(std::move(first), last, value, proj);
        if (first != last)
        {
            for (I i {std::next(first)}; i != last; ++i)
            {
                if (value != std::invoke(proj, *i))
                {
                    *first = ranges::iter_move(i);
                    ++first;
                }
            }
        }
        return {first, last};
    }
 
    template<ranges::forward_range R, class T, class Proj = std::identity>
    requires std::permutable<ranges::iterator_t<R>> &&
             std::indirect_binary_predicate<
                 ranges::equal_to, std::projected<
                     ranges::iterator_t<R>, Proj>, const T*>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, const T& value, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), value, std::move(proj));
    }
};
 
inline constexpr remove_fn remove {};
remove_if
struct remove_if_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    constexpr ranges::subrange<I>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        first = ranges::find_if(std::move(first), last, pred, proj);
        if (first != last)
        {
            for (I i {std::next(first)}; i != last; ++i)
            {
                if (!std::invoke(pred, std::invoke(proj, *i)))
                {
                    *first = ranges::iter_move(i);
                    ++first;
                }
            }
        }
        return {first, last};
    }
 
    template<ranges::forward_range R, class Proj = std::identity,
             std::indirect_unary_predicate<
                 std::projected<ranges::iterator_t<R>, Proj>> Pred>
    requires std::permutable<ranges::iterator_t<R>>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), pred, std::move(proj));
    }
};
 
inline constexpr remove_if_fn remove_if {};

[editar] Ejemplo

#include <algorithm>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
 
int main()
{
    std::string v1 {"No - se requiere - diagnóstico"};
    std::cout << std::quoted(v1) << " (v1, tamaño: " << v1.size() << ")\n";
    const auto ret = std::ranges::remove(v1, ' ');
    std::cout << std::quoted(v1) << " (v1 después de `remove`, tamaño: " << v1.size() << ")\n";
    std::cout << ' ' << std::string(std::distance(v1.begin(), ret.begin()), '^') << '\n';
    v1.erase(ret.begin(), ret.end());
    std::cout << std::quoted(v1) << " (v1 después de `erase`, tamaño: " << v1.size() << ")\n\n";
 
    // remove_if con predicado unario personalizado:
    auto rm = [](char c) { return !std::isupper(c); };
    std::string v2 {"Falla En La Sustitución No Es Un Error"};
    std::cout << std::quoted(v2) << " (v2, tamaño: " << v2.size() << ")\n";
    const auto [first, last] = std::ranges::remove_if(v2, rm);
    std::cout << std::quoted(v2) << " (v2 después de `remove_if`, tamaño: " << v2.size() << ")\n";
    std::cout << ' ' << std::string(std::distance(v2.begin(), first), '^') << '\n';
    v2.erase(first, last);
    std::cout << std::quoted(v2) << " (v2 después de `erase`, tamaño: " << v2.size() << ")\n\n";
 
    // se crea una vista sobre cadena dentro de un contenedor que se modifica por `remove_if`:
    for (std::string s : {"Optimización de Objeto Pequeño", "Parámetro de Plantilla de No Tipo"})
        std::cout << std::quoted(s) << " => "
                  << std::string_view {begin(s), std::ranges::remove_if(s, rm).begin()}
                  << '\n';
}

Posible salida:

"No - se requiere - diagnóstico" (v1, tamaño: 31)
"No-serequiere-diagnósticostico" (v1 después de `remove`, tamaño: 31)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
"No-serequiere-diagnóstico" (v1 después de `erase`, tamaño: 26)
 
"Falla En La Sustitución No Es Un Error" (v2, tamaño: 39)
"FELSNEUE La Sustitución No Es Un Error" (v2 después de `remove_if`, tamaño: 39)
 ^^^^^^^^
"FELSNEUE" (v2 después de `erase`, tamaño: 8)
 
"Optimización de Objeto Pequeño" => OOP
"Parámetro de Plantilla de No Tipo" => PPNT

[editar] Véase también

Copia un rango de elementos, omitiendo aquellos que satisfacen un criterio específico
(niebloid) [editar]
Elimina elementos duplicados consecutivos en un rango.
(niebloid) [editar]
Elimina elementos que satisfacen un criterio específico.
(plantilla de función) [editar]