Espacios de nombres
Variantes

std::unique

De cppreference.com
 
 
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
 
<tbody> </tbody>
Definido en el archivo de encabezado <algorithm>
template< class ForwardIt > ForwardIt unique( ForwardIt first, ForwardIt last );
(1) (constexpr desde C++20)
template< class ExecutionPolicy, class ForwardIt > ForwardIt unique( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last );
(2) (desde C++17)
template< class ForwardIt, class BinaryPred > ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPred p );
(3) (constexpr desde C++20)
template< class ExecutionPolicy, class ForwardIt, class BinaryPred > ForwardIt unique( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, BinaryPred p );
(4) (desde C++17)

Elimina todos los elementos excepto el primero de cada grupo consecutivo de elementos equivalentes del rango [firstlast) y devuelve un iterador posterior al final para el nuevo final del rango.

1) Los elementos se comparan utilizando operator==.
Si operator== no establece una relación de equivalencia, el comportamiento no está definido.
3) Los elementos se comparan utilizando el predicado binario dado p.
Si p no establece una relación de equivalencia, el comportamiento no está definido.
2,4) Igual que (1,3), pero ejecutado de acuerdo con policy.
Estas sobrecargas no participan en la resolución de sobrecarga a menos que std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> (hasta C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> (desde C++20) sea verdadera.

Explicación

La eliminación se realiza desplazando los elementos en el rango de tal manera que los elementos que no se deben eliminar aparezcan al principio del rango.

  • El desplazamiento se realiza mediante la asignación de copia (hasta C++11)asignación de movimiento (desde C++11).
  • La operación de eliminación es estable: el orden relativo de los elementos que no se deben eliminar permanece igual.
  • La secuencia subyacente de [firstlast) no se acorta con la operación de eliminación. Dado result como el iterador devuelto:
  • Cada elemento de [resultlast) tiene un estado válido pero no especificado, porque la asignación de movimiento puede eliminar elementos al moverse desde elementos que originalmente estaban en ese rango.
(desde C++11)

Parámetros

first, last - El rango de elementos a procesar.
policy - La política de ejecución a usar. Véase política de ejecución para más detalles.
p - Predicado binario que devuelve ​true si los elementos deben tratarse como iguales.

La signatura de la función predicado deberá ser equivalente a la siguiente:

bool pred(const Tipo1 &a, const Tipo2 &b);

Mientras que la signatura no necesita tener const &, la función no debe modificar los objetos que se le han pasado y debe ser capaz de aceptar todos los valores de tipo (posiblemente const) Tipo1 y Tipo2 independientemente de la categoría de valor (por lo tanto, no se permite Tipo1 &, ni Tipo1 a menos que para Tipo1 un movimiento sea equivalente a una copia (desde C++11)).
Los tipos Tipo1 y Tipo2 deben ser tales que un objeto de tipo ForwardIt puede ser desreferenciado y luego convertido implícitamente a ambos. ​

Requisitos de tipo
-
ForwardIt debe satisfacer los requisitos de ForwardIterator.
-
El tipo del ForwardIt desreferenciado debe cumplir con los requisitos de AsignablePorMovimiento.

Return value

Un ForwardIt al nuevo final del rango.

Complexity

Dada N as std::distance(first, last):

1,2) Exactamente max(0,N-1) comparaciones usando operator==.
3,4) Exactamente max(0,N-1) aplicaciones del predicado p.

Excepciones

Las sobrecargas con un parámetro de plantilla llamado ExecutionPolicy (política de ejecución) reportan errores tales que:

  • Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y la política de ejecución es una de las tres políticas estándar, se llama a std::terminate. Para cualquier otra política de ejecución, el comportamiento está definido por la implementación.
  • Si el algoritmo falla al asignar memoria, se lanza std::bad_alloc.

Posible implementación

Véanse también las implementaciones en libstdc++, libc++, y MSVC STL.

unique (1)
template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last)
{
    if (first == last)
        return last;
    
    ForwardIt result = first;
    while (++first != last)
        if (!(*result == *first) && ++result != first)
            *result = std::move(*first);
    
    return ++result;
}
unique (3)
template<class ForwardIt, class BinaryPredicate>
ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p)
{
    if (first == last)
        return last;
    
    ForwardIt result = first;
    while (++first != last)
        if (!p(*result, *first) && ++result != first)
            *result = std::move(*first);
    
    return ++result;
}

Notas

Una llamada a unique suele ir seguida de una llamada a la función miembro erase de un contenedor para eliminar elementos del contenedor.

Ejemplo

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
    // una vector que contiene varios elementos duplicados
    std::vector<int> v{1, 2, 1, 1, 3, 3, 3, 4, 5, 4};
    auto print = [&](int id)
    {
        std::cout << "@" << id << ": ";
        for (int i : v)
            std::cout << i << ' ';
        std::cout << '\n';
    };
    print(1);

    // eliminar duplicados consecutivos (adyacentes)
    auto last = std::unique(v.begin(), v.end());
    // v ahora alberga {1 2 1 3 4 5 4 x x x}, donde 'x' es indeterminada
    v.erase(last, v.end());
    print(2);

    // sort seguido de unique, para eliminar todos los duplicados
    std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5}
    print(3);

    last = std::unique(v.begin(), v.end());
    // v ahora alberga {1 2 3 4 5 x x}, donde 'x' es indeterminada
    v.erase(last, v.end());
    print(4);
}

Salida:

@1: 1 2 1 1 3 3 3 4 5 4
@2: 1 2 1 3 4 5 4
@3: 1 1 2 3 4 4 5
@4: 1 2 3 4 5

Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
LWG 202 C++98 El comportamiento no estaba claro si los elementos
se comparan utilizando una relación de no equivalencia,
El comportamiento no está definido en este caso.

Véase también

Encuentra dos elementos contiguos idénticos (o que satisfagan un predicado dado).
(plantilla de función) [editar]
Crea una copia de un rango de elementos que no contiene duplicados consecutivos.
(plantilla de función) [editar]
Elimina elementos que satisfacen un criterio específico.
(plantilla de función) [editar]
Elimina elementos consecutivos duplicados.
(función miembro pública de std::list) [editar]
(C++11)
Elimina elementos consecutivos duplicados.
(función miembro pública de std::forward_list) [editar]
Elimina elementos duplicados consecutivos en un rango.
(niebloid) [editar]