std::unique
Определено в заголовке <algorithm> | ||
|---|---|---|
template< class ForwardIt > ForwardIt unique( ForwardIt first, ForwardIt last ); | (1) | (constexpr с C++20) |
template< class ExecutionPolicy, class ForwardIt >
ForwardIt unique( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last );
| (2) | (с C++17) |
template< class ForwardIt, class BinaryPred > ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPred p ); | (3) | (constexpr с C++20) |
template< class ExecutionPolicy,
class ForwardIt, class BinaryPred >
ForwardIt unique( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, BinaryPred p );
| (4) | (с C++17) |
Удаляет все элементы, кроме первого, из каждой группы подряд идущих эквивалентных элементов диапазона [first, last) и возвращает итератор за новым концом диапазона.
p.p не задаёт отношение эквивалентности, поведение не определено.policy.true: |
| (до C++20) |
|
| (с C++20) |
Пояснение
Удаление выполняется путём сдвига элементов диапазона так, чтобы элементы, которые не нужно удалять, оказались в начале диапазона.
- Сдвиг выполняется с помощью оператора копирующего присваивания(до C++11)оператора перемещающего присваивания(с C++11).
- Операция удаления является стабильной: относительный порядок элементов, которые не нужно удалять, сохраняется.
- Базовая последовательность
[first,last)не укорачивается в результате операции удаления. Пустьresult— возвращённый итератор: - Все итераторы в
[result,last)по-прежнему являются разыменовываемыми.
| (с C++11) |
Параметры
| first, last | - | пара итераторов, задающих диапазон обрабатываемых элементов |
| policy | - | политика выполнения |
| p | - | бинарный предикат, возвращающий true, если элементы следует считать равными. Сигнатура функции-предиката должна быть эквивалентна следующей: boolpred(constType1&a,constType2&b); Хотя сигнатура не обязана содержать |
| Требования к типам | ||
-ForwardIt должен удовлетворять требованиям LegacyForwardIterator. |
||
-Тип разыменованного ForwardIt должен удовлетворять требованиям MoveAssignable. |
||
Возвращаемое значение
ForwardIt на новый конец диапазона.
Сложность
Пусть \(\scriptsize N\)N — std::distance(first, last):
p.Исключения
Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:
- Если выполнение функции, вызванной в рамках алгоритма, приводит к выбросу исключения, а
ExecutionPolicyявляется одной из стандартных политик, вызываетсяstd::terminate. Для любого другогоExecutionPolicyповедение определяется реализацией. - Если алгоритму не удаётся выделить память, выбрасывается
std::bad_alloc.
Возможная реализация
См. также реализации в libstdc++, libc++ и 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;
}
|
Примечания
За вызовом unique обычно следует вызов метода-члена контейнера erase, который фактически удаляет элементы из контейнера.
Пример
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
// a vector containing several duplicate elements
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);
// remove consecutive (adjacent) duplicates
auto last = std::unique(v.begin(), v.end());
// v now holds {1 2 1 3 4 5 4 x x x}, where 'x' is indeterminate
v.erase(last, v.end());
print(2);
// sort followed by unique, to remove all duplicates
std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5}
print(3);
last = std::unique(v.begin(), v.end());
// v now holds {1 2 3 4 5 x x}, where 'x' is indeterminate
v.erase(last, v.end());
print(4);
}
Вывод:
@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
Отчёты об ошибках
Следующие отчёты об ошибках, меняющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение согласно опубликованному стандарту | Правильное поведение |
|---|---|---|---|
| LWG 202 | C++98 | поведение было неясным, если элементы сравнивались с помощью отношения, не являющегося отношением эквивалентности | в этом случае поведение не определено |
См. также
| находит первые два соседних элемента, которые равны (или удовлетворяют заданному предикату) (шаблон функции и функциональный объект-алгоритм) |
|
|
(C++20) | |
| создаёт копию части диапазона, не содержащую повторяющихся подряд элементов (шаблон функции и функциональный объект-алгоритм) |
|
|
(C++20) | |
| удаляет элементы, удовлетворяющие заданным критериям (шаблон функции и функциональный объект-алгоритм) |
|
|
(C++20)(C++20) | |
| удаляет повторяющиеся подряд элементы (открытая функция-член std::list<T,Allocator>) |
|
| удаляет повторяющиеся подряд элементы (открытая функция-член std::forward_list<T,Allocator>) |
|
| удаляет повторяющиеся подряд элементы (открытая функция-член std::hive<T,Allocator>) |
|
|
(C++20) | удаляет повторяющиеся подряд элементы в диапазоне (функциональный объект-алгоритм) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/unique