Namespaces
Variants

std::unique

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p.ej. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de secuencia modificadoras
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Ordenación y operaciones relacionadas
Operaciones de partición
(C++11)    

Operaciones de ordenación
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjunto (en rangos ordenados)
Operaciones de fusión (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
Definido en el 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 excepto el primer elemento de cada grupo consecutivo de elementos equivalentes del rango [first, last) y devuelve un iterador al final (past-the-end) para el nuevo final del rango.

1) Los elementos se comparan usando operator==.
Si operator== no establece una relación de equivalencia, el comportamiento no está definido.
3) Los elementos se comparan usando 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 según policy.
Estas sobrecargas participan en la resolución de sobrecarga solo si el valor de la siguiente expresión es true:

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)

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 copy assignment (until C++11) move assignment (since C++11) .
  • La operación de eliminación es estable: el orden relativo de los elementos que no se eliminan permanece igual.
  • La secuencia subyacente de [ first , last ) no se acorta mediante la operación de eliminación. Dado result como el iterador devuelto:
  • Cada elemento de [ result , last ) tiene un estado válido pero no especificado, porque la asignación de movimiento puede eliminar elementos moviendo desde elementos que originalmente estaban en ese rango.
(desde C++11)

Parámetros

first, last - el par de iteradores que define el rango de elementos a procesar
policy - la política de ejecución a utilizar
p - predicado binario que retorna ​ true si los elementos deben tratarse como iguales.

La firma de la función predicado debe ser equivalente a la siguiente:

bool pred ( const Type1 & a, const Type2 & b ) ;

Aunque la firma no necesita tener const & , la función no debe modificar los objetos pasados a ella y debe poder aceptar todos los valores de tipo (posiblemente const) Type1 y Type2 independientemente de la categoría de valor (por lo tanto, Type1 & no está permitido , ni tampoco Type1 a menos que para Type1 un movimiento sea equivalente a una copia (since C++11) ).
Los tipos Type1 y Type2 deben ser tales que un objeto de tipo ForwardIt pueda ser desreferenciado y luego convertido implícitamente a ambos. ​

Requisitos de tipo
-
ForwardIt debe cumplir con los requisitos de LegacyForwardIterator .
-
El tipo desreferenciado de ForwardIt debe cumplir con los requisitos de MoveAssignable .

Valor de retorno

Un ForwardIt al nuevo final del rango.

Complejidad

Dado N como std:: distance ( first, last ) :

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

Excepciones

Las sobrecargas con un parámetro de plantilla llamado ExecutionPolicy reportan errores de la siguiente manera:

  • Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y ExecutionPolicy es uno de los standard policies , std::terminate es llamado. Para cualquier otro ExecutionPolicy , el comportamiento está definido por la implementación.
  • Si el algoritmo falla al asignar memoria, std::bad_alloc es lanzado.

Implementación posible

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

único (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;
}
único (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 normalmente va seguida de una llamada a la función miembro erase del contenedor para eliminar realmente los elementos del contenedor.

Ejemplo

#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
    // un 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 contiene {1 2 1 3 4 5 4 x x x}, donde 'x' es indeterminado
    v.erase(last, v.end());
    print(2);
    // ordenar 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 contiene {1 2 3 4 5 x x}, donde 'x' es indeterminado
    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 que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 202 C++98 el comportamiento no estaba claro si los elementos
se comparan usando una relación no de equivalencia
el comportamiento es
indefinido en este caso

Véase también

encuentra los dos primeros elementos adyacentes que son iguales (o satisfacen un predicado dado)
(plantilla de función &objeto función de algoritmo)
crea una copia de un rango de elementos que no contiene duplicados consecutivos
(plantilla de función &objeto función de algoritmo)
elimina elementos que satisfacen criterios específicos
(plantilla de función &objeto función de algoritmo)
elimina elementos duplicados consecutivos
(función miembro pública de std::list<T,Allocator>)
elimina elementos duplicados consecutivos
(función miembro pública de std::forward_list<T,Allocator>)
elimina elementos duplicados consecutivos en un rango
(objeto función de algoritmo)