简体   繁体   中英

How to use std::unique to remove unique character in vector (c++)

I need to remove unique characters in a vector v.erase(unique(v.begin(),v.end())); what is problem with this.
input:wxwwm
output:wxm

 `vector<string>v;    
  string s;   
  cin >>s;   
  v.push_back(s);   
  v.erase(unique(v.begin(),v.end()),v.end());     
  for(auto i=v.begin();i!=v.end();i++)    
  {  
   cout <<*i;  
   }`

EDIT: This answer was applicable to the previous, slightly unclear version of the question. For the answer to the current question, see Caleth's answer.


std::unique removes the adjacent duplicates (actually pushes them to the end of the given range, to make them very suitable for later removal with erase ). That's not what you want.

If you want to remove unique elements, then I would propose a solution based on counting the distinct elements' occurrences and them removing those which occur only once. Take a look at this function:

template <typename T>
void remove_unique(std::vector<T>& vec) {
    std::map<T, int> occurrences {};

    for(const auto& element : vec) {
        occurrences[element]++;
    }

    const auto to_remove = std::remove_if(vec.begin(), vec.end(),
            [&occurrences](const auto& element) {
                return occurrences[element] == 1;
            }
    );

    vec.erase(to_remove, vec.end());
}

This will remove all unique elements from a std::vector containing any type (given it's copyable).

It uses a std::map to count the occurrences of every element in a vector and then uses std::remove_if , which will (similarily to std::unique ) push elements that satisfy a certain criteria to the end of the range, to make them sutiable for actual removal. The certain criteria in this example is the satisfaction of a predicate - a lambda, which checks if the given element occurred only once (this information is provided by our map, which we capture in the lambda). Afterwards, we simply remove those elements with erase call.

Usage:

int main() {
    // two 2s and two 3s
    std::vector<int> vec {1, 2, 4, 3, 0, 2, 9, 3};

    remove_unique(vec);

    for(const auto i : vec) {
        std::cout << i << ' ';
    }
}

Output of this program is: 2 3 2 3 . All unique elements have been removed

std::unique doesn't do what you require here. You will have to do something else.

From this reference (emphasis mine)

Eliminates all but the first element from every consecutive group of equivalent elements

A simple way to test if you have seen an element previously is to add it to a set.

std::string s = "wxwwm";
std::set<char> seen;
s.erase(std::remove_if(s.begin(), s.end(), [&seen](char c){ return !seen.insert(c).second; }), s.end());
std::cout << s; // outputs wxm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM