How do you determine the last valid item in an STL container

If I iterate over an STL container, I sometimes need to know if the current item is the last in the sequence. Is there a better way to then do something like this? Can I convert rbegin () somehow?

std::vector<int> myList;

// ....
std::vector<int>::iterator lastit = myList.end();  
lastit--;

for(std::vector<int>::iterator it = myList.begin(); it != myList.end(); it++)  {
     if(it == lastit)
     {
        // Do something with last element
     }
     else
     {
       //  Do something with all other elements
     }

      

+1


a source to share


8 answers


Try to run

std::vector<int>::iterator it2 = (++it);
if ( it2 == myList.end() ) {
  ...
}

      



The following should work as well

if ( it+1 == myList.end() ) {
  // it is last
  ...
}

      

+3


a source


Maybe you can iterate backward (use rbegin

/ rend

) and put your special task before the loop, or replace the final check with it != lastit

and put special handling after the loop



+2


a source


I will have doubts about my design if some elements need to be handled differently, but this suggestion is a little cleaner for me (remember to check empty containers)

std::vector<int>::iterator lastit = myList.end();
if (lastit != myList.begin())
{
  lastit--;
  for(std::vector<int>::iterator it = myList.begin(); it != lastit; ++it)
  {
     // Do
  }
  // Do with last
}

      

+1


a source


Use reverse iteration , so you only have one end () - one-way computation (note rbegin () + 1) and no comparisons :

for(vector<int>::iterator it = myValues.rbegin()+1; it != myValues.rend(); it++) {
    cout << *it << endl;
}
cout << "Process last one: " << *myValues.rbegin() << endl;

      

Also, for a vector <>, the computation of end () - 1 is probably fast, so you can also do it like this:

for(vector<int>::iterator it = myValues.begin(); it != myValues.end()-1; it++) {
    cout << *it << endl;
}
cout << "Process last one: " << *myValues.rbegin() << endl;

      

If you don't want to process the element after the loop, you can:

for(vector<int>::iterator it = myValues.rbegin(); it != myValues.rend(); it++) {
    if(it == myValues.rbegin())
        cout << "Process last one: " << *it << endl;
    else
        cout << *it << endl;
}

      

+1


a source


For a random access iterator like a vector, you don't need a temporary one. You can say:

if ( it + 1 == v.end() ) {
   // at one before end
}

      

Edit: And even for non-random access types, std: can be used; distance:

if ( distance( it, v.end() ) == 1 ) {
   // at one before end
}

      

0


a source


An important question: why create a loop if you are doing something special for 1 element. Why not do something special for the 3rd element? Every fourth? ...

Just iterate over the elements that need to be treated the same, write separate code to treat others.

Look at the answers to this question .

0


a source


Why not:

if(!myList.empty())
    last_it = myList.begin() + myList.size()-1;
else
    last_it = myList.end();


//or
    last_it = myList.empty() ? myList.end() : myList.begin() + myList.size() - 1;

      

0


a source


If you are using a vector, it is actually much easier to use an integer index to iterate over:

std::vector<int> myList;
for (unsigned int i = 0; i < myList.size(); i++)
{
  if (i == (myList.size() - 1))
  {
    processDifferently (myList[i])
  }
  else
  {
    process (myList[i])
  }
}

      

Minimizing the number of calls to myList.size () is left as an exercise for the OP :)

-1


a source







All Articles