Joel Seah
Joel Seah

Reputation: 714

Start iterating vector from the nth element

I'm trying to iterate a vector from the nth element onwards. Not sure how should i go about doing this.

I have a vector A and B. My vector A has 10 elements of PC1-PC10 and my vector B has 20 elements of User1-User20.
So what I want to do is that when both my vector A and B reaches the 10th element, meaning to say the last element for vector A, I want to repeat iterating vector A but start iterating vector B from the 11th element so that I can do some stuff with it.

Below is the simplified code that I came up with but technically its about the same thing:

vector<string>::iterator b = vecB.begin();
for (int i = 1; i < 2; i++) {
    for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
        if (a == vecA.end()) {
            b = vecB.begin() + 10; //here the iterator for verB should start from the 11th element
        }
    ++b
    }
}

Should I mess with the iterator for vector B? Or is there another alternative?

EDIT
It seems that I have been asking the wrong question after all. I have marked the answer to this question and will be posting another shortly. Thanks for the quick response to my question!

Upvotes: 3

Views: 3648

Answers (5)

Gillespie
Gillespie

Reputation: 6561

I actually prefer to manually iterate over vectors pre-C++11 because it looks way cleaner and more readable than iterators:

for (unsigned int i = 0; i < my_vector.size(); i++) {
    my_vector[i]; //Do Something
}

You can specify the range you want to iterate over simply by modifying the for loop conditional (i.e. unsigned int i = n)

Edit: Before downvoting actually read my entire answer. Using iterators on vectors is overly verbose and makes your code virtually unreadable. If there is a legitimate reason this method should not be used in favor of iterators, then please leave a comment.

Most people aren't looking for an ultra-generic, drop-in-any-container solution. Most people know they need a dynamic list, vector fits the bill, so why not make your code easy to read for the next guy?

Upvotes: -1

StenSoft
StenSoft

Reputation: 9617

You don't need to change the iterator for B, it will automatically continue with 11th element. But you need to restart iteration on A at the beginning of the for loop (or you would work with a.end() which is not a valid element):

if (a == vecA.end()) {
    a = vecA.begin();
}

Also you should iterate over both but check for end on b only; if you check on a, the for would end before the if would turn true:

for (auto a = vecA.begin(), b = vecB.begin(); b != vecB.end(); ++a, ++b)

You can see the whole code here.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727047

The if condition inside the nested loop will never be true, because it conflicts with the loop condition:

for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
// This check ----------------------------------^^^^^^^^^^^^^^^
// guarantees that this will never succeed:
//      vvvvvvvvvvvvvvv
    if (a == vecA.end()) {
        ...
    }
}

You should rewrite the code like this:

vector<string>::iterator b = vecB.begin();
// Check that vecB has sufficient number of elements before entering the loop.
for (int i = 1 ; i < 2 ; i++) {
    for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; ++a, ++b) {
        ...
    }
    // At this point we know for sure that a == vecA.end(),
    // because it is a post-condition of the for loop above.
    b = std::next(vecB.begin(), 11);
}

The call of ++b can be moved into the loop header.

Note the use of std::next: although

b = vecB.begin() + 10;

compiles for vectors, it is not guaranteed for all kinds of containers. Use std::next instead:

b = std::next(vecB.begin(), 11);

Note: This code makes an assumption that vecB has at least 11 elements more than vecA does. This may be OK if you check that assumption before entering the loop. If this assumption is broken, the code would have undefined behavior.

Upvotes: 4

eerorika
eerorika

Reputation: 238461

Others have already answered how to reset or advance an iterator, so I'll just answer, how to solve your problem in a simpler way. It's much simpler to iterate two vectors in parallel using the index rather than two iterators:

// assumes vecB is bigger than vecA as described in the question
for (std::size_t i = 0; i < vecB.size(); i++) {
    auto user = vecB[i];
    auto pc = vecA[i % vecA.size()];
}

Pay attention to how the smaller vector is iterated using the remainder operator.

Upvotes: 1

R Sahu
R Sahu

Reputation: 206717

In addition to using std::next, as shown in the answer by @dasblinkenlight, you can also use std::advance.

b = vecB.begin();
std::advance(b, 10);

Upvotes: 0

Related Questions