C++ для начинающих.

Алгоритм unique().

Template class ForwardIterator.

ForwardIterator.

Unique( ForwardIterator first,

ForwardIterator last );

Template class ForwardIterator, class BinaryPredicate.

ForwardIterator.

Unique( ForwardIterator first,

ForwardIterator last, BinaryPredicate pred );

Все группы равных соседних элементов заменяются одним. В первом варианте при сравнении используется оператор равенства, определенный для типа элементов в контейнере. Во втором варианте два элемента равны, если бинарный предикат pred для них возвращает true. Таким образом, слово mississippi будет преобразовано в misisipi. Обратите внимание, что три буквы 'i' не являются соседними, поэтому они не заменяются одной, как и две пары несоседних 's'. Если нужно, чтобы все одинаковые элементы были заменены одним, придется сначала отсортировать контейнер.

На самом деле поведение unique() интуитивно не совсем очевидно и напоминает remove(). В обоих случаях размер контейнера не изменяется: каждый уникальный элемент помещается в очередную позицию, начиная с first.

В нашем примере физически будет получено слово misisipippi, где ppi - остаток, "отходы" алгоритма. Возвращаемый итератор указывает на начало этого остатка и обычно передается алгоритму erase() для удаления ненужных элементов. (Поскольку для встроенного массива операция erase() не поддерживается, то лучше воспользоваться алгоритмом unique_copy().) Алгоритм unique_copy().

Template class InputIterator, class OutputIterator.

OutputIterator.

Unique_copy( InputIterator first, InputIterator last,

OutputIterator result );

Template class InputIterator, class OutputIterator,

Class BinaryPredicate.

OutputIterator.

Unique_copy( InputIterator first, InputIterator last,

OutputIterator result, BinaryPredicate pred );

Unique_copy() копирует входной контейнер в выходной, заменяя группы одинаковых соседних элементов на один элемент с тем же значением. О том, что понимается под равными элементами, говорилось при описании алгоритма unique(). Чтобы все дубликаты были гарантированно удалены, входной контейнер необходимо предварительно отсортировать. Возвращаемый итератор указывает на элемент за последним скопированным.

#include algorithm.

#include vector.

#include string.

#include iterator.

#include assert.h.

Template class Type.

Void print_elements( Type elem ) { cout elem " "; }.

Void (*pfi)( int ) = print_elements;

Void (*pfs)( string ) = print_elements;

Int main().

{

Int ia[] = { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5 };

Vectorint,allocator vec( ia, ia+10 );

Vectorint,allocator::iterator vec_iter;

// последовательность не изменяется: нули не стоят рядом.

// печатается: 0 1 0 2 0 3 0 4 0 5.

Vec_iter = unique( vec.begin(), vec.end() );

For_each( vec.begin(), vec.end(), pfi ); cout "\n\n";

// отсортировать вектор, затем применить unique: модифицируется.

// печатается: 0 1 2 3 4 5 2 3 4 5.

Sort( vec.begin(), vec.end() );

Vec_iter = unique( vec.begin(), vec.end() );

For_each( vec.begin(), vec.end(), pfi ); cout "\n\n";

// удалить из контейнера ненужные элементы.

// печатается: 0 1 2 3 4 5.

Vec.erase( vec_iter, vec.end() );

For_each( vec.begin(), vec.end(), pfi ); cout "\n\n";

String sa[] = { "enough", "is", "enough",

"enough", "is", "good" };

Vectorstring,allocator svec( sa, sa+6 );

Vectorstring,allocator vec_result( svec.size() );

Vectorstring,allocator::iterator svec_iter;

Sort( svec.begin(), svec.end() );

Svec_iter = unique_copy( svec.begin(), svec.end(),

Vec_result.begin() );

// печатается: enough good is.

For_each( vec_result.begin(), svec_iter, pfs );

Cout "\n\n";

}