Assigning a std::set to a 2D std::vector of ints

Refresh

April 2019

Views

87 time

1

I'm trying to make a integer Matrix with no numbers repeated and its elements sorted so I was making it with a std::vector<std::vector<int>> but then, searching on internet and Stackoverflow, I've found something called std:set which I see is a container and it has just the 2 properties I'm looking for: no repeated elements and sorted. Cool!

The first thing I've tried is to have that:

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

But then I don't get how can I initialize it. I've tried the same way I would do with normal vectors...something like std::vector<std::vector<int>> Matrix(row, std::vector<int>(col, 0)); But ofc it didn't work.

So my next idea was to have:

  • A 2d vector matrix.
  • A std::set with all the values

And then assign that set to the matrix so maybe will be easily for me to work with that but I'm still getting a lot of problems that I hope you can help me understanding where am I wrong...

int row=3,col=4;
//I create the Matrix and initialize it with 0
std::vector<std::vector<int>> Matrix(row, std::vector<int>(col, 0));

std::set<int> SetNumbers;
for (int i = 0; i < row*col; i++)
    SetNumbers.insert((rand() % 100) + 1); // I want to random generate the 12 numbers

std::set<int>::iterator it;
for (it = SetNumbers.begin(); it != SetNumbers.end(); ++it)
    cout << "SET: "<<(*it) << endl; // Here I print on screen the numbers of the set

// Lets TRY to assign the set to the 2d vector. I use auto to avoid errors on types
for (auto it1 = Matrix.begin(); it1 != Matrix.end(); ++it1)
{
    for (auto it2 = (*it1).begin(); it2 != (*it1).end(); ++it2)
    {
        *it2 = 4; // That WORKS so maybe with the next line I get what I want...
        *it2 = SetNumbers.? // Ofc not... even intellisense doesn't work so bad way
        Matrix.assign(SetNumbers.begin(), SetNumbers.end()); // Gives Error and complains about Matrix 
         (*it2) = SetNumbers[index]; // Discovered  that set CAN't be accessed with [] 
        (*it2) = SetNumbers.begin() // Wrong too

    }
}

Another try I made is with function std::copy

    std::copy(SetNumbers.begin(), SetNumbers.end(), Matrix.begin());

But it gives me a Error 'error C2679: binary '=' : no operator found which takes... `

And if I try to sort by rows inside the first loop with something like

 std::copy(SetNumbers.begin(), SetNumbers.end(), (*it1).begin());

Then the program crashes and I don't know what else can I try...

Thank you so much!

P.D.: Also, another question came up... I know that using iterators is a way to avoid using the [] operator but could I make something like //Cart[it1][it2].insert(number); inside the double loop??

P.D.2: Clarification about Sort

If I have numbers 1,2,3,4,5,6,7,8,9 I want my Matrix sorted like

1,4,7
2,5,8
3,6,9

So I was thinking of sorting it in general which will give me a Matrix like:

1,2,3
4,5,6
7,8,9

And then swap positions... But maybe there is a better way of doing it.

2 answers

0

First, by creating a std::vector<std::vector<std::set<int>>>, you've effectively created a 3-dimensional construct.

Second, the problem with using nested vectors or sets is that their uniqueness isn't bound to the flattened elements -- it's bound to the nested vector/set itself. This means you would still have to check each individual element in the nested containers to make sure they're unique from the elements in their sibling containers.

You'd be better off just using a single std::set<int> to represent your matrix with its dimensions defined elsewhere (as you've already done with int row=3,col=4). One caveat: you'd have to erase the values you want to modify (via std::set::erase()) then re-insert the modified value as sets don't allow direct modification of their elements.

Using a std::vector<int> would work, too, but as you're aware, they aren't sorted or unique by default. That said, it's fairly trivial to make them sorted and distinct. This would only be recommended if you aren't planning on modifying many of the values in the vector as it would really only be cost-effective to perform sorting and distinction after you've added all the values you wish to add. You'd have to do it again every time you modify a value which could turn into a slow mess.

0

What you want to do is copy the values from your set into your matrix.

We can do this with std::copy and a flattening iterator

std::copy(SetNumbers.begin(), SetNumbers.end(), flatten(Matrix.begin(), Matrix.end()));

This is also available in the Ranges TS, as the join view

ranges::copy(SetNumbers, Matrix | ranges::view::join());