4

I have 2D vector like this: vector<vector<int>>. I am using iterators to go through it by rows BUT what would be the best practice to go through it by columns?

This is the code I use for iterating by rows:

vector<vector<int>> vMatrix (4, vector<int>(4));
vector<vector<int>>::iterator itRow;
vector<int>::iterator itCol;

for (itRow = vMatrix.begin(); itRow != vMatrix.end(); itRow++)
{
    for (itCol = itRow->begin(); itCol != itRow->end(); itCol++) 
    {
        // do some stuff
    }
}

Kind regards, Milen Vichev

milen.vichev
  • 122
  • 1
  • 7

2 Answers2

1

Possible solution in this case:

for (int col = 0; col < 4; col++)
{
    for (int row = 0; row < 4; row++) 
    {
        // do some stuff
    }
}
Ilya
  • 4,583
  • 4
  • 26
  • 51
  • Thank you for the response. I was looking for a solution with iterators as it should be faster. – milen.vichev May 30 '14 at 08:00
  • Ok, I see. But vector of vectors is bad structure for fast access to elements in orthogonal direction. I think, there are no better solution for this structure. And in your case (small 4x4 matrix) it will not be effective to use something else. – Ilya May 30 '14 at 08:25
  • In fact the elements in the matrix are not INT but objects, but for the ease of the example I used INT. I needed to store objects in the form of matrix so I chose vector for the fast access to the elements. Will you prefer other way of storing ? – milen.vichev May 30 '14 at 10:25
  • Sometimes it is very effective to use std::valarray for such operations. But I don't know your task, so I can't be sure that it will be perfect for you. – Ilya May 30 '14 at 10:35
  • I need to go through the matrix and depending on the value of the current cell, I do check on the next cell and maybe alter its value – milen.vichev May 30 '14 at 10:38
  • It sounds like good task for std::valarray, because it is very powerfull container. See std::slice_array, std::mask_array, std::indirect_array and other it's methods! – Ilya May 30 '14 at 10:40
1

I think a way of doing that is through the transpose of the matrix:

std::vector<std::vector<int>> transpose(const std::vector<std::vector<int>> &m)
{
  using std::vector;

  vector<vector<int>> result(m[0].size(), vector<int>(m.size()));

  for (vector<int>::size_type i(0); i < m[0].size(); ++i)
    for (vector<int>::size_type j(0); j < m.size(); ++j)
      result[i][j] = m[j][i];

  return result;
}

and

std::vector<std::vector<int>>::iterator itCol;
std::vector<int>::iterator itRow;
std::vector<std::vector<int>> t(transpose(vMatrix));

for (itRow = t.begin(); itRow != t.end(); itRow++)
  for (itCol = itRow->begin(); itCol != itRow->end(); itCol++)
  {
    // ...
  }

Nothing needs to change inside the loop body, but it's SLOW.

You could gain some speed modifying transpose to return a "view" of the transpose of the matrix:

std::vector<std::vector<int *>> transpose(const std::vector<std::vector<int>> &)

Anyway even this solution is slower than accessing elements via operator[].

Probably, if code refactoring is an option, a good solution would be to change from a vector of vectors to a 1D vector for better code locality (something like https://stackoverflow.com/a/15799557/3235496).

Community
  • 1
  • 1
manlio
  • 18,345
  • 14
  • 76
  • 126