0

I am trying to create a program to retain only unique elements in a vector

for example:

vector<string> i = "one", "one", "two".

the output would be:

vector<string> i = "one", "two"

**** This is an implementation of the answer as a function. I get the error vector iterator incompatible when I run it with a sample vector.

void simplifyVector(vector<string> i){

    /*vector<string>*/;

    sort(i.begin(), i.end());

    auto iter = unique(i.begin(), i.end());

    while (iter != i.end())
    {
        i.erase(iter);
    }

    for (const auto &s : i)
    {
        cout << s << " ";
    }
    cout << endl;

}
b4hand
  • 9,550
  • 4
  • 44
  • 49

1 Answers1

1

Use sort and unique. Use sort to but all duplicate values adjacent to each other than unique puts all vales that are adjacent to each other at the end and returns an iterator pointing to the first duplicate element. Then we use a while loop to remove those elements. Remember generic algorithms never delete elements in a container.

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

int main()
{
    std::vector<std::string> i = {"one", "one", "two"};

    std::sort(i.begin(), i.end());

    auto iter = std::unique(i.begin(), i.end());

    erase(iter, i.end());

    for (const auto &s : i)
    {
        std::cout << s << " ";
    }
    std::cout << std::endl;

    return 0;
}
ChajusSaib
  • 167
  • 12
  • 2
    You don't need to write an erase loop. `std::vector::erase` has an overload that takes two iterators so you just could do `i.erase(iter, i.end());` – Blastfurnace Jun 30 '15 at 18:33
  • could you please explain the line "for (const auto &s : i)" ? –  Jun 30 '15 at 18:36
  • @Naan: That is a [`range-based for loop`](http://en.cppreference.com/w/cpp/language/range-for), a C++11 feature. Your compiler probably supports it but you might need to use a compiler option to enable it. – Blastfurnace Jun 30 '15 at 18:47
  • I am using visual c++ 2010, and the compiler doesn't seem to recognize it. –  Jun 30 '15 at 18:49
  • do you know how to enable it? –  Jun 30 '15 at 18:49
  • @Naan: I think that feature was added in Visual C++ 2012, sorry. – Blastfurnace Jun 30 '15 at 18:51
  • it seems that it is not enabled in ms visual studio 2010 –  Jun 30 '15 at 18:51
  • do you know how to convert it so that the compiler can recognize it? –  Jun 30 '15 at 18:52
  • 1
    The indexed-for loop basically does this under the hood: `typedef std::vector::iterator iterator; for(iterator iter = i.begin(); iter != i.end(); iter++) { const std::string& s = *iter;` – celticminstrel Jun 30 '15 at 18:57
  • @Naan: You can still write a standard loop using an index or iterators like we've been doing for decades. That should be covered in any good C++ book or countless internet tutorials. – Blastfurnace Jun 30 '15 at 18:57
  • (But don't put it all on one line like that!) – celticminstrel Jun 30 '15 at 18:58
  • Of course, you could loop over it like an array instead, if you prefer, using `i.size()`. – celticminstrel Jun 30 '15 at 18:58
  • so, how i understand it is like this. the expression to the right of the colon is the range expression, like i < 500. To the left of the colon is the i = 0, right? –  Jun 30 '15 at 19:01
  • i dont think i understood how range based for loops work. –  Jun 30 '15 at 19:03
  • @Naan: In the code above it reads like "for every `s` in `i` perform the body of the loop". There are some subtleties involved like deducing the type of `s` and taking it as a const reference. It's actually simple once you get used to it. – Blastfurnace Jun 30 '15 at 19:11
  • when i use the code above in vs 2012, i get a run time error –  Jun 30 '15 at 19:33
  • the run time error is vector iterators incompatible –  Jun 30 '15 at 19:35
  • @Naan 'vector iterators incompatible' means you are trying to compare iterators from two different vectors. – ChajusSaib Jul 01 '15 at 00:22
  • Seems like `erase` is dangling there (and g++ agrees it's not declared in this scope).Maybe `i.erase` was what was intended. – Ron Burk Nov 08 '20 at 04:12