C ++ std :: unique не показывает то, что я ожидаю от него - PullRequest
1 голос
/ 30 мая 2019

Я пытался найти, содержит ли вектор дубликаты (пожалуйста, не предоставляйте алгоритм для проверки дубликатов). Я придумал это странное поведение.std :: unique для вектора 1,2,3,1 должен сделать его равным 1,2,3,1, возвращая итератор к 1, но при стирании итератор возвращался до vector.end () Я получил вектор такого же размера, какЯ оригинальный вектор.Вот фрагмент кода, изображающего указанное поведение (доступно в ideone )

    vector<int> nums2 = {1,2,3,4};  
    vector<int> nums = {1,2,3,1};
    cout << "nums1" << endl;
    vector<int> a(nums.begin(), nums.end());
    auto ip = unique(nums.begin(), nums.begin()+nums.size());
    nums.resize( std::distance(nums.begin(),ip) );
    cout << a.size() <<  " " << nums.size() << endl;

    cout << "Nums2" << endl;
    vector<int> a2(nums2.begin(), nums2.end());
    auto ip2 = unique(nums2.begin(), nums2.begin()+nums2.size());
    nums.resize( std::distance(nums2.begin(),ip2) );
    cout << a2.size() <<  " " << nums2.size();

Фактический результат равен

nums1
4 4
Nums2
4 4

, но он должен был быть

nums1
4 3
Nums2
4 4

Ответы [ 3 ]

6 голосов
/ 30 мая 2019

std::unique удаляет только последовательные дубликаты.От cppreference.com по std::unique:

Исключает все, кроме первого элемента, из каждой последовательной группы эквивалентных элементов из диапазона [first, last) и возвращает итератор «конец конца» для нового логического конца диапазона.

Ваши единицы не являются последовательными, поэтому они не удаляются.Это ожидаемое поведение.Быстрое решение - сначала std::sort ваш диапазон.

2 голосов
/ 30 мая 2019

Если вы хотите удалить дубликаты элементов, сохраняя при этом их первые вхождения в порядке, unique - это не то, что вам нужно.Вместо этого используйте unordered_set, чтобы отслеживать элементы, которые вы видели до сих пор.(Вы можете сделать это с помощью remove_if, но я бы не советовал, если вы не знакомы с семантикой захвата лямбда-выражений; просто сделайте это в цикле for и прочитайте, как правильно удалять элементы из вектора вдля цикла.)

1 голос
/ 30 мая 2019

Вы неправильно понимаете, что делает std :: unique;он исключает все, кроме первого из последовательных последовательностей элементов.То есть он не удалит дубликаты, которые находятся рядом.Таким образом, чтобы удалить дубликаты, вы должны убедиться, что все дубликаты расположены рядом друг с другом;Самый простой способ сделать это с помощью std :: vector - это сначала применить std :: sort, а затем std :: unique.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...