intcreator
intcreator

Reputation: 4414

How can I remove elements of vectors in a set of vectors?

If I have a set of unique vectors, how can I (for example) delete the second element in each vector? I have created the following simple example:

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

using namespace std;

int main()
{
    vector<int> myVec1 = {0, 1, 2, 3, 4, 5};
    vector<int> myVec2 = {3, 5, 7, 2, 4, 1};
    vector<int> myVec3 = {2, 5, 3, 8, 6, 9};

    set<vector<int>> mySet;
    mySet.insert(myVec1);
    mySet.insert(myVec2);
    mySet.insert(myVec3);

    // right now this for loop deletes an element from a copy only
    for(auto item : mySet) item.erase(item.begin() + 2);

    for(auto item : mySet)
    {
        for(auto element : item) cout << " " << element;
        cout << "\n";
    }
}

This example can be compiled and run on cpp.sh.

Possible solutions I have considered:

Upvotes: 0

Views: 1343

Answers (3)

Jerry Coffin
Jerry Coffin

Reputation: 490683

I would use std::transform to take the data from the existing set, modify as needed, and insert the results into a new set, then swap the old set with the new one:

std::set<std::vector<int> > mySet { 
    {0, 1, 2, 3, 4, 5},
    {3, 5, 7, 2, 4, 1},
    {2, 5, 3, 8, 6, 9}
};

std::set<std::vector<int>> temp;

std::transform(mySet.begin(), mySet.end(), 
    std::inserter(temp, temp.end()), 
    [](std::vector<int> s) { s.erase(s.begin() + 1); return s; }
);

std::swap(temp, mySet);

If you're dealing with a lot of data, you might be better off getting a vector from the input set, erasing it from the input set, erasing the element from that vector, and inserting the result into the output.

Upvotes: 1

user4590120
user4590120

Reputation:

You would need to remove the vector from the set of vectors before manipulating it and after the manipulation reinsert the vector.

Since this would involve a lot of creating/copying vectors, you could use pointers to vectors -- in which case you would need your own compare function object:

struct compare
{        bool operator()(
                 const std::shared_ptr<std::vector<int> > &_r0,
                 const std::shared_ptr<std::vector<int> > &_r1) const
         {        return *_r0 < *_r1;
         }
};
std::set<std::shared_ptr<std::vector<int> >, compare> sSet;

in order to delete the second element in each vector, I would first create a copy of all pointers:

std::vector<std::shared_ptr<std::vector<int> > > sCopy(
        sSet.begin(),
        sSet.end());
sSet.clear();
for (auto p = sCopy.begin(), pEnd = sCopy.end();
        p != pEnd;
        ++p)
{        auto rVectorPtr = *p;
         if (rVectorPtr->size() > 1)
                 rVectorPtr->erase(rVectorPtr->begin() + 1);
         sSet.insert(rVectorPtr);
}

Upvotes: 0

Carlton
Carlton

Reputation: 4297

Probably not the solution you're looking for, but you could have your set hold pointers to vectors instead. This works for me:

int main() {

    vector<int> myVec1 = {0, 1, 2, 3, 4, 5};
    vector<int> myVec2 = {3, 5, 7, 2, 4, 1};
    vector<int> myVec3 = {2, 5, 3, 8, 6, 9};

    set<vector<int>*> mySet;
    mySet.insert(&myVec1);
    mySet.insert(&myVec2);
    mySet.insert(&myVec3);

    for(vector<int>* item : mySet) item->erase(item->begin() + 2);

    for(vector<int>* item : mySet)
    {
        for(auto element : *item) cout << " " << element;
        cout << "\n";
    }

    return 0;
}

Upvotes: 0

Related Questions