1

I have to create a generic function that removes all duplicates in a vectorInt a vectorBook which is a class i created that has getYear and getName functions. I'm not sure how to make the the function because the vectorInt is compared because the Book gets compared with getName and getYear. Int is compared on one level while Book is compared on two levels.

template<class T> vector<T> removeDuplicates(vector<T> n){
for(unsigned int i = 0; i < n.size();i++){
   T current = n.at(i);
   for(unsigned int j = i + 1; j < n.size(); j++){
       T compare = n.at(j);
       if(current == compare)
           n.erase(n.begin() + j);  
  }
} 
return n;
}

Thanks for the help

EDIT:

Tried using this

 template <class T> std::vector<T> removeDuplicates(std::vector<T> vec)
 {
 std::sort( vec.begin(), vec.end() );
 vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() );
 return vec;
 }

but for books i keep getting an error

class Book { 
public:
Book();
Book(std::string, int);
int getYear() const {
return year;
 }
std::string getName() const {
return name;
}
bool operator==(Book const &);

  private:
  std::string name;
  int year;
};
user1179321
  • 797
  • 1
  • 10
  • 24
  • To be able to sort books, you need to define a strict weak order on the books and tell `std::sort()` about this order. The easiest way to do so is to enable `book1 < book2`, e.g., by implementing the less-than operator `bool operator< (Book const& b0, Book const& b1)` to yield a lexicographical order of the two books. – Dietmar Kühl Oct 03 '12 at 19:18

2 Answers2

5

A pure STL version:

#include <algorithm>

template <class T> std::vector<T> removeDuplicates(std::vector<T> vec)
{
    std::sort( vec.begin(), vec.end() );
    std::vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() );
    return vec;
}

You can make it more efficient by taking and returning references rather than copies.

Code snarfed shamelessly from answer to this question.

Community
  • 1
  • 1
Wug
  • 12,956
  • 4
  • 34
  • 54
  • Note that this technique will reorder the vector contents. This may or may not be important. – cdhowie Oct 03 '12 at 18:47
  • True. However, one could probably work something out from the linked question that doesn't involve reordering. – Wug Oct 03 '12 at 18:56
  • This works for int but when i try to do it with Book i keep getting an error – user1179321 Oct 03 '12 at 19:09
  • Post it in the question. chances are you're missing a comparison operator, probably == or – Wug Oct 03 '12 at 19:10
2

As long as Book has a usable operator == implementation, this should work just fine. If not, then you will need to create a specialization for Book or add such an operator:

class Book
{
    // ...
public:
    bool operator==(Book const &);
};

bool Book::operator==(Book const & other)
{
    return getName() == other.getName() && getYear() == other.getYear();
}

Note that you have an off-by-one error in your traversal -- if you do wind up deleting an item, the very next item will be skipped over. Consider using this loop instead:

for (vector<T>::iterator i = n.begin; i != n.end(); ++i) {
    for (vector<T>::iterator j = i + 1; j != n.end(); /* */) {
        if (*i == *j) {
            n.erase(j++);
        } else {
            ++j;
        }
    }
}
cdhowie
  • 158,093
  • 24
  • 286
  • 300