Ricardo Sanchez
Ricardo Sanchez

Reputation: 5167

How to keep track of current and previous iterator on a c++ vector?

I have one vector container and I would like to make a subtraction operation on the values of its content using the current iterator against the previous iterator, any help will be much appreciated

Upvotes: 1

Views: 4272

Answers (6)

Edward
Edward

Reputation: 6300

std::vector's iterator is a RandomAccessIterator, so you can perform integer arithmetic on it. Thus, you don't need a separate "current" and "previous" pointer, as long as you start your iteration from begin() + 1:

vector<Foo> myVec = ...;
if(myVec.size() > 1) { 
    for(vector<Foo>::iterator iter = myVec.begin()+1; iter != myVec.end(); iter++) {
        Foo current = *iter;
        Foo previous = *(iter - 1);
        Foo subtraction = current - previous;
        ...
    }
}

Of course, you can't subtract the current and previous element if there are fewer than two elements in your vector. The size check might be redundant if you know your input vector will always have at least two elements, but I included it just to be safe.

Upvotes: 3

lip
lip

Reputation: 688

There are namely three more-or-less elegant ways to solve your problem.

Define a new functor

And use it in a for_each iteration

template<class T>
struct substractor {
    substractor() : last(nullptr) {}
    void operator()(T& item) const
    {
        if(last != nullptr)
            *last -= item;
        last = &item;
    }
    mutable T* last;
};
...
vector<int> v = {3, 2, 1};
for_each(v.begin(), v.end(), substractor<int>());

Define a new algorithm

Some kind of pair in-place transform here

template<typename It, typename Op>
void pair_transform(It begin, It end, Op op){
    while(begin != end)
    {
        It next = std::next(begin);
        if(next == end) break;
        *begin = op(*begin, *next);
        ++begin;
    }
}
...
vector<int> w = {3, 2, 1};
pair_transform(w.begin(), w.end(), std::minus<int>());

Keep it standard, use transform

IMHO the best one :) Concise, standard, nowhere else to look in order to understand this code.

vector<int> z = {3, 2, 1};
std::transform(z.begin(), z.end() - 1, z.begin() + 1, z.begin(), 
    std::minus<int>());

Upvotes: 0

johnsyweb
johnsyweb

Reputation: 141860

An alternative:

for (auto previous = v.begin(), current = previous + 1, end = v.end();
    previous != end && current != end;
    ++previous, ++current)
{
    std::cout << *current << " - " << *previous << " = " << *current - *previous << std::endl;
}

Upvotes: 0

Balog Pal
Balog Pal

Reputation: 17183

if(v.size() < 2)
   return;
auto curr = v.begin();
auto next = curr;
++next;
do
{
  whatever(*next - *curr );
  curr = next++;
} while( next != v.end() )

Upvotes: 2

Mark Ransom
Mark Ransom

Reputation: 308392

vector<MyClass>::iterator itPrevious = my_vec.begin();
vector<MyClass>::iterator itCurrent = itPrevious;
if (itCurrent != my_vec.end())
{
    for (++itCurrent;  itCurrent != my_vec.end();  ++itCurrent)
    {
        // do something with itPrevious and itCurrent
        itPrevious = itCurrent;
    }
}

Upvotes: 6

Nicola Musatti
Nicola Musatti

Reputation: 18226

Given you asked for a vector, you can use iterator arithmetic:

#include <vector>
#include <iostream>

int main() {
    std::vector<int> v{ 1, 2, 3, 4 };
    for ( auto i = v.begin(); i != v.end(); ++i ) {
        if ( i != v.begin() )
            *i = *i - *(i-1);
    }
    for ( auto i : v )
        std::cout << i << std::endl;
}

Upvotes: 2

Related Questions