简体   繁体   中英

How to iterate over a 2d vector using a 1d index

Given a vector of vector of int (for example), the following piece of code allows me to map the flat position into a 2d index and access the element:

int x = 0, y = 0, acc = 0;

while ((acc = myVector[x].size()+acc) <= position) {
     x++;
     y= acc;
}
y = position - y;

I was wondering if there is a way to iterate over all the elements of my 2d vector using a single pointer thus incrementing it by the position number.

EDIT1:

std::vector<std::vector<int>> myVector;

myVector.emplace_back();

for (int i = 0; i < 10; i++) {
    myVector[0].emplace_back(0);
}

myVector.emplace_back();
for (int i = 0; i < 5; i++) {
    myVector[0].emplace_back(1);
}

myVector.emplace_back();
for (int i = 0; i < 8; i++) {
    myVector[0].emplace_back(2);
}

for (auto row : myVector) {
    for (auto col : row) {
        std::cout << col << std::endl;
    }
}

What I need is to create a pointer to the first element pointed by myVector[0][0] and then create a link between the end of the first row and the beginning of the next one so I can iterate over it using a single pointer. If I need the element at position 12 then just by incrementing the pointer I can get the element in position (1,1). Basically I'm trying to emulate the behaviour of the c arrays using std::vectors

In c++20, there is direct support for this functionality using the <ranges> header. So you could simply do:

namespace srv = std::ranges::views;

for (auto i : myVector | srv::join)
     std::cout << i << std::endl;

Here's a demo .

With range-v3, you can make a vector of the joined view like this:

namespace rv = ranges::views;
    
auto j = myVector | rv::join | ranges::to<std::vector<int>>;

and then index into it arbitrary positions.

Here's a demo .

Write your own container class which does the following:

  1. Take a vector of vectors as the constructor argument. Store the vector of vectors address as its member.
  2. implement get(size_t p) to iterate through like below:
size_t i;
for (i = 0; i < v.size() && p > v[i].size(); i++)
{
   p -= v[i].size();
}
return v[i][p];
  1. overload [] to point to get

I was wondering if there is a way to iterate over all the elements of my 2d vector using a single pointer

No , there isn't. You can't assume the elements of the first vector are followed by the elements of the second vector, etc.

You can instead use a std::vector<int> to store all you elements contiguously, then construct a std::vector<std::span<int>> as a "2d" view of those elements

std::vector<int> raw;

for (int i = 0; i < 10; i++) {
    raw.emplace_back(0);
}

for (int i = 0; i < 5; i++) {
    raw.emplace_back(1);
}

for (int i = 0; i < 8; i++) {
    raw.emplace_back(2);
}

std::vector<std::span<int>> myVector;
myVector.emplace_back(raw.data(), 10);
myVector.emplace_back(raw.data() + 10, 5);
myVector.emplace_back(raw.data() + 15, 8);

for (auto row : myVector) {
    for (auto col : row) {
        std::cout << col << std::endl;
    }
}

See it live

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM