2

Hi i'm trying to remove duplicate values from my vector. It is set up as a vector. This vector contains a list of vectors, in each of the interior vectors is 3 strings.

I tried:

removeCopies.erase( unique(removeCopies.begin(), removeCopies.end() ), removeCopies.end());

but it still leaves some strings inside the interior vector like:

mainVector: {
interiorVector1: string 1: "book", string 2: "noun", string3: "A book"
interiorVector2: string 1: "book", string 2: "noun", string3: "a BOok"
}

I also can't just change it all to lowercase, I can't edit the values inside of the vector.

If you need a better explanation, please ask. Thank you.

edit:

I tried

unique(stringVec.begin(), stringVec.end(), [](const string &a, const string 
&b) { return lowercase(a) == lowercase(b); }), stringVec.end()

where lowercase() turns the entire string to lowercase. But it doesn't allow me to access the interior vector strings to do this.

1 Answer 1

3

Just like std::sort, std::unique accepts a BinaryPredicate that in the case of unique is used for equals-comparison:

template< class ForwardIt, class BinaryPredicate >
constexpr ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPredicate p );

If you provide a case-insensitive predicate, then it should work just fine. I recommend boost::iequals if you don't want to re-invent the wheel.

The following code won't work for your specific nested-vector example, but if you only had strings inside the vector the resultant code would look something like:

removeCopies.erase(std::unique(begin(removeCopies), end(removeCopies), boost::iequals), end(removeCopies));

In your case, you'll probably want to write a custom lambda that internally uses iequals to perform element-wise comparison.

Edit: Here is a discount-version of iequals:

bool iequals(const std::string& lhs, const std::string& rhs)
{
   if (lhs.size() != rhs.size())
      return false;
   for(size_t i = 0; i < lhs.size(); ++i)
   {
       if (std::tolower(lhs[i]) != std::tolower(rhs[i]))
          return false;
   }
   return true;
}
Sign up to request clarification or add additional context in comments.

4 Comments

ah I believe we are not allowed to use external libraries like boost.
@code1331: It's fairly straightforward to write your own version of iequals. Use std::toupper (or std::tolower) to compare characters between strings.
I tried string lowercase(string x) { transform(x.begin(), x.end(), x.begin(), [](char x) { return tolower(x); }); return x; } unique(stringVec.begin(), stringVec.end(), [](const string &a, const string &b) { return lowercase(a) == lowercase(b); } ), stringVec.end() sorry it wont let me format.
@code1331 you don't need to declare a temporary string and use std::transform. You will get better performance with a regular loop that indexes into both the strings for comparison (and as a result will terminate after the minimum length). Inside the loop use std::tolower to get a lowercase version of each character in the respective strings. Then compare those characters for equivalance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.