std::unique
| 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 [first, last) y devuelve un iterador posterior al final para el nuevo final del rango.
operator==.operator== no establece una relación de equivalencia, el comportamiento no está definido.p.p no establece una relación de equivalencia, el comportamiento no está definido.policy.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
[first,last)no se acorta con la operación de eliminación. Dadoresultcomo el iterador devuelto:
- Todos los iteradores en
[result,last)siguen siendo desreferenciables.
- Todos los iteradores en
|
(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:
Mientras que la signatura no necesita tener |
| 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):
operator==.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) | |
| Crea una copia de un rango de elementos que no contiene duplicados consecutivos. (plantilla de función) | |
| Elimina elementos que satisfacen un criterio específico. (plantilla de función) | |
| Elimina elementos consecutivos duplicados. (función miembro pública de std::list)
| |
(C++11) |
Elimina elementos consecutivos duplicados. (función miembro pública de std::forward_list)
|
(C++20) |
Elimina elementos duplicados consecutivos en un rango. (niebloid) |