user1310873 user1310873 - 1 month ago 33
C++ Question

remove duplicate STL vector in STL vector

I have a STL vector of STL vector which contains integer values. Some inside vectors are duplicating but their element order is not the same. Now, I want to get a vector of vector without having any duplicate inner vectors. I've been seen the following method:

std::vector<std::vector<int>> myVec;
std::sort(myVec.begin(), myVec.end());
myVec.erase(std::unique(myVec.begin(), myVec.end()), myVec.end());


the problem is that i want to eleminate duplicates keeping the order of elements of each order(original order or without sort it), what is the best way to do this? is there another way more efficient?

Example:

1 6 4 5
3 1 5 2----> result of elimination: 1 6 4 5
2 1 3 5 3 1 5 2


Thanks in advance

vacing

Answer

The question is not exactly clear. So I am going to give two answers.

(1) If you wish to remove duplicates but retaining 1 copy while maintaining myVec's order, you need to use a set.

std::vector< std::vector<int> > myVec;
//or std::unordered_set if you expect mostly unique sorted inner vectors
std::set< std::vector<int> > exists; 
std::vector< std::vector<int> > tmpVec;

for (std::size_t i=0, N=myVec.size(); i<N; ++i)
{
    std::vector<int> key(myVec[i]);
    std::sort(key.begin(), key.end());
    if (exists.find(key) == exists.end())
    {
        exists.insert(key);
        tmpVec.push_back(std::vector<int>());
        std::swap(myVec[i], tmpVec.back());
     }
}

std::swap(tmpVec, myVec);

(2) If you wish to remove all elements that appear more than once in myVec you need a map of counters.

std::vector< std::vector<int> > myVec;
//or std::unordered_map if you expect mostly unique sorted inner vectors
std::map< std::vector<int>, unsigned > counters; 

// first loop to count
for (std::size_t i=0, N=myVec.size(); i<N; ++i)
{
    std::vector<int> key(myVec[i]);
    std::sort(key.begin(), key.end());
    ++counters[key];
}

// second loop to filter
std::vector< std::vector<int> > tmpVec;
for (std::size_t i=0, N=myVec.size(); i<N; ++i)
{
    std::vector<int> key(myVec[i]);
    std::sort(key.begin(), key.end());
    if (counters[key] == 1)
    {
        tmpVec.push_back(std::vector<int>());
        std::swap(myVec[i], tmpVec.back());
     }
}

std::swap(tmpVec, myVec);

Both solutions respects the order of elements in myVec and retains the original order in the inner vectors' elements.

Comments