std::ranges:: unique
std::ranges
| Non-modifying sequence operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Modifying sequence operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Partitioning operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Sorting operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Binary search operations (on sorted ranges) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Set operations (on sorted ranges) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Heap operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Minimum/maximum operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Permutation operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Fold operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operations on uninitialized storage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Return types | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definido en el encabezado
<algorithm>
|
||
|
Firma de llamada
|
||
|
template
<
std::
permutable
I,
std::
sentinel_for
<
I
>
S,
class
Proj
=
std::
identity
,
std::
indirect_equivalence_relation
<
std
::
projected
<
I, Proj
>>
|
(1) | (desde C++20) |
|
template
<
ranges::
forward_range
R,
class
Proj
=
std::
identity
,
std::
indirect_equivalence_relation
<
std
::
projected
<
ranges::
iterator_t
<
R
>
, Proj
>>
|
(2) | (desde C++20) |
[
first
,
last
)
y devuelve un subrango
[
ret
,
last
)
, donde
ret
es un iterador más allá del final para el nuevo final del rango.
*(i - 1)
y
*i
se consideran equivalentes si
std::
invoke
(
comp,
std::
invoke
(
proj,
*
(
i
-
1
)
)
,
std::
invoke
(
proj,
*
i
)
)
==
true
, donde
i
es un iterador en el rango
[
first
+
1
,
last
)
.
Las entidades similares a funciones descritas en esta página son algorithm function objects (conocidas informalmente como niebloids ), es decir:
- No se pueden especificar listas de argumentos de plantilla explícitas al llamar a cualquiera de ellos.
- Ninguno de ellos es visible para la búsqueda dependiente de argumento .
- Cuando cualquiera de ellos es encontrado mediante la búsqueda no calificada normal como el nombre a la izquierda del operador de llamada a función, la búsqueda dependiente de argumento queda inhibida.
Contenidos |
Parámetros
| first, last | - | el par iterador-centinela que define el rango de elementos a procesar |
| r | - | el rango de elementos a procesar |
| comp | - | el predicado binario para comparar los elementos proyectados |
| proj | - | la proyección a aplicar a los elementos |
Valor de retorno
Devuelve
{
ret, last
}
, donde
ret
es un iterador que apunta después del final para el nuevo final del rango.
Complejidad
Para rangos no vacíos, exactamente ranges:: distance ( first, last ) - 1 aplicaciones del predicado correspondiente comp y no más del doble de aplicaciones de cualquier proyección proj .
Notas
La eliminación se realiza desplazando (mediante asignación de movimiento) los elementos en el rango de tal manera que los elementos que no se deben eliminar aparecen al principio del rango. El orden relativo de los elementos que permanecen se conserva y el
tamaño físico
del contenedor no cambia. Los iteradores en
[
ret
,
last
)
(si los hay) siguen siendo desreferenciables, pero los elementos mismos tienen valores no especificados (según la
MoveAssignable
postcondición).
Una llamada a
ranges::unique
a veces es seguida por una llamada a la función miembro
erase
del 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 modelan el
Erase–remove
idiom
.
Implementación posible
struct unique_fn { template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_equivalence_relation<std::projected<I, Proj>> C = ranges::equal_to> constexpr ranges::subrange<I> operator()(I first, S last, C comp = {}, Proj proj = {}) const { first = ranges::adjacent_find(first, last, comp, proj); if (first == last) return {first, first}; auto i {first}; ++first; while (++first != last) if (!std::invoke(comp, std::invoke(proj, *i), std::invoke(proj, *first))) *++i = ranges::iter_move(first); return {++i, first}; } template<ranges::forward_range R, class Proj = std::identity, std::indirect_equivalence_relation<std::projected<ranges::iterator_t<R>, Proj>> C = ranges::equal_to> requires std::permutable<ranges::iterator_t<R>> constexpr ranges::borrowed_subrange_t<R> operator()(R&& r, C comp = {}, Proj proj = {}) const { return (*this)(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj)); } }; inline constexpr unique_fn unique {}; |
Ejemplo
#include <algorithm> #include <cmath> #include <complex> #include <iostream> #include <vector> struct id { int i; explicit id(int i) : i {i} {} }; void print(id i, const auto& v) { std::cout << i.i << ") "; std::ranges::for_each(v, [](auto const& e) { std::cout << e << ' '; }); std::cout << '\n'; } int main() { // un vector que contiene varios elementos duplicados std::vector<int> v {1, 2, 1, 1, 3, 3, 3, 4, 5, 4}; print(id {1}, v); // eliminar duplicados consecutivos (adyacentes) const auto ret = std::ranges::unique(v); // v ahora contiene {1 2 1 3 4 5 4 x x x}, donde 'x' es indeterminado v.erase(ret.begin(), ret.end()); print(id {2}, v); // ordenar seguido de unique, para eliminar todos los duplicados std::ranges::sort(v); // {1 1 2 3 4 4 5} print(id {3}, v); const auto [first, last] = std::ranges::unique(v.begin(), v.end()); // v ahora contiene {1 2 3 4 5 x x}, donde 'x' es indeterminado v.erase(first, last); print(id {4}, v); // unique con comparación y proyección personalizadas std::vector<std::complex<int>> vc { {1, 1}, {-1, 2}, {-2, 3}, {2, 4}, {-3, 5} }; print(id {5}, vc); const auto ret2 = std::ranges::unique(vc, // considerar dos números complejos iguales si sus partes reales son iguales en módulo: [](int x, int y) { return std::abs(x) == std::abs(y); }, // comp [](std::complex<int> z) { return z.real(); } // proj ); vc.erase(ret2.begin(), ret2.end()); print(id {6}, vc); }
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 5) (1,1) (-1,2) (-2,3) (2,4) (-3,5) 6) (1,1) (-2,3) (-3,5)
Véase también
|
(C++20)
|
crea una copia de un rango de elementos que no contiene duplicados consecutivos
(objeto función de algoritmo) |
|
(C++20)
|
encuentra los dos primeros elementos adyacentes que son iguales (o satisfacen un predicado dado)
(objeto función de algoritmo) |
|
(C++20)
(C++20)
|
elimina elementos que cumplen criterios específicos
(objeto función de algoritmo) |
|
elimina elementos duplicados consecutivos en un rango
(plantilla de función) |
|
|
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>
)
|