0

I have a 2D and 3D vector

using namespace std;

vector< vector<int> > vec_2d;
vector<vector<vector<int>>> vec_3d

I know how to iterate 2D vector row-wise using two iterators. The first the iterator of the "rows" and the second the iterators of the "columns" in that "row". Now, I need to iterate over 2D vector such that the first iterator becomes the iterator of the "columns" and the second the iterator of the rows in that "column" i.e. column-wise.

David Scarlett
  • 3,171
  • 2
  • 12
  • 28
user109260
  • 878
  • 7
  • 22
  • Just use indexes. – Igor Tandetnik Dec 02 '16 at 04:16
  • Just checking if there are better methods that using indexes. – user109260 Dec 02 '16 at 04:25
  • It's been my experience that if you have a container that is indexed, iterators are generally slower to use, especially since dereferencing, to get the value, adds to the overhead. – tinstaafl Dec 02 '16 at 04:28
  • 3
    If you're traversing a 2D array column-wise, the overhead of iterators will be the least of your problems. Even with indexes the fact that such a pattern negates caching will slow down memory access enormously. – David Scarlett Dec 02 '16 at 04:32

2 Answers2

2

Using iterators, this will be very difficult. I'd say you would probably need to implement your own iterator classes inheriting from std::iterator<random_access_iterator_tag, Type>.

If you don't actually need to use iterators and really have a good reason for wanting to traverse vectors of vectors in such an odd way (and are aware of how this will slow down memory access by preventing caching) then it could easily be done using indexes.

Here's an example using indexes which handles the tricky case where the inner vectors are not all of the same length.

using namespace std;

int main()
{
    vector< vector<int> > vec_2d = { {1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10} };

    bool is_col_out_of_bounds = false;
    for (size_t col=0; ! is_col_out_of_bounds; col++)
    {
        is_col_out_of_bounds = true;
        for (size_t row=0; row<vec_2d.size(); row++)
        {
            if (col < vec_2d[row].size())
            {
                is_col_out_of_bounds = false;
                cout << vec_2d[row][col] << endl;
            }
        }
    }

    return 0;
}

Output:

1
4
8
2
5
9
3
6
10
7

If you want to guarantee that all rows are of the same length, then vector<array<T, N>> may be a better choice.

Community
  • 1
  • 1
David Scarlett
  • 3,171
  • 2
  • 12
  • 28
1

A simple answer: Who said your layout should be interpreted row-wise? A std::vector<std::vector<Foo>> has no knowledge about rows and columns, so let the outer-most vector represent columns instead of rows.

This is a pain when printing to the terminal, which is likely to do it row-wise, but if column layout is preferred internally, do it that way.

user877329
  • 6,717
  • 8
  • 46
  • 88