1

I'm just messing around with some lambda expressions and I decided to attempt to remove duplicate elements from a vector. However, it isn't working. I put in some debug logging and it appears that std::count isn't returning the expected result. Any would would be greatly appreciated.

For reference, I know this isn't the most efficient way to remove an item from a vector! I was just experimenting with lambdas as I don't understand them as well as I would like to.

Thanks!

#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
    std::vector<int> v = { 0, 0, 1, 2, 4, 4, 4 };

    std::remove_if(v.begin(), v.end(), [&v](const int &x) 
    { 
        return std::count(v.begin(), v.end(), x) > 1;
    });

    std::cout << "\n\nResult:\n";
    for (const auto& i : v) { std::cout << i << std::endl; }

    return 0;
}
Barry
  • 286,269
  • 29
  • 621
  • 977
jhammond
  • 1,916
  • 2
  • 15
  • 29

1 Answers1

3

That's because remove_if doesn't actually remove elements:

Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range.

That's why it returns an iterator, so you can then:

A call to remove is typically followed by a call to a container's erase method, which erases the unspecified values and reduces the physical size of the container to match its new logical size.

That is:

v.erase(std::remove_if(v.begin(), v.end(), [&v](const int &x) 
{ 
    return std::count(v.begin(), v.end(), x) > 1;
}), v.end());

This is known as the Erase-remove idiom.

Note that if all you want to do is remove duplicates, and you don't care about preserving the order, you could use std::sort and std::unique (you need to sort because unique only "removes" consecutive duplicate elements):

std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());

arr_sea
  • 841
  • 10
  • 16
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Thanks for the insight! Two things: 1) I am attempting to preserve order and 2) this unfortunately removes all duplicates to the point where an element won't exist anymore. For example, there are two 0s in the vector, but I actually want 1 of them removed (leaving the second). Is what I am trying to do not possible in the way I am trying to do it? Thanks! – jhammond Apr 13 '15 at 21:03
  • @jhammond Here are two good solutions: [using set](http://stackoverflow.com/a/10520258/2069064) and [not using set](http://stackoverflow.com/a/1464684/2069064). – Barry Apr 13 '15 at 21:09