简体   繁体   中英

Getting index of unique elements in a vector

Is there any STL/Boost function in C++ that allows me to find the indices of all unique elements in a vector?

I have seen many solutons to find unique elements, but I need their index.

  vector<int> v = { 1,1,1, 2,2,2,2, 3, 3, ,4,5,5,5,5,5,5 };// already sorted

Either I need first index of unique elemnt

vector<int> unique_index={0,3,7,9,10};

or I need last index of unique elements

vector<int> unique_index={2,6,8,9,15};

A simple way (aside from just keeping track of what the last element was) is to use a std::set to test if the current element is unique in the elements of the vector -- seen so far, and populate your unique indexes as you go. This provides a single pass through to collect the indexes where the first unique element is seen, eg

#include <iostream>
#include <vector>
#include <set>

int main (void) {
    
    std::vector<int> v = { 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5 },
                uniqueidx{};
    std::set<int> s{};
    
    for (size_t i = 0; i < v.size(); i++)
        if (s.insert(v[i]).second)
            uniqueidx.push_back(i);
    
    for (const auto i : uniqueidx) 
        std::cout << i << '\n';
}

Example Use/Output

$ ./bin/set_index_of_unique_in_vector
0
3
7
10
11

( note: the last two values are 10 and 11 , not 9 and 10 -- you are missing a value in your vector initialization, eg 3, ,4 )

If you just wanted a simple-old loop to do the same thing, you could use:

#include <iostream>
#include <vector>

int main (void) {
    
    std::vector<int> v = { 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5 },
                uniqueidx{};
    
    for (size_t i = 0; i < v.size(); i++)
        if (!i || v[i-1] != v[i])
            uniqueidx.push_back(i);
    
    for (const auto i : uniqueidx) 
        std::cout << i << '\n';
}

(same output)

The benefit of the approach with std::set is you leave the determination of uniqueness up to std::set , with the simple loop -- it's up to you....

Look things over and let me know if you have questions.

Similar to David's answer of using std::set , you could also use std::map with its member function try_emplace(key, value) :

#include <iostream>
#include <vector>
#include <map>

int main (void) {
    
    std::vector<int> v = { 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5 };
    std::map<int, int> m;
    
    for (size_t i = 0; i < v.size(); i++)
    {
        // `i` is only entered if the `m[v[i]]` isn't filled yet.
        m.try_emplace(v[i], i);
    }

    for (auto [valueFromV, indexFromV] : m) 
    {
        std::cout << indexFromV << '\n';
    }
}

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