Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skipping iterator

I have a sequence of values that I'd like to pass to a function that takes a (iterator begin, iterator end) pair. However, I only want every second element in the original sequence to be processed.

Is there a nice way using Standard-Lib/Boost to create an iterator facade that will allow me to pass in the original sequence? I figured something simple like this would already be in the boost iterators or range libraries, but I didn't find anything.

Or am I missing another completely obvious way to do this? Of course, I know I always have the option of copying the values to another sequence, but that's not what I want to do.

Edit: I know about filter_iterator, but that filters on values - it doesn't change the way the iteration advances.

like image 317
ltjax Avatar asked Apr 16 '11 10:04

ltjax


2 Answers

I think you want boost::adaptors::strided

like image 111
Nathan Phillips Avatar answered Nov 15 '22 15:11

Nathan Phillips


struct TrueOnEven {
 template< typename T >
 bool operator()(const T&) { return mCount++ % 2 == 0; }
 TrueOnEven() : mCount(0) {}
 private:
  int mCount;
};

int main() {
 std::vector< int > tVec, tOtherVec;
 ...
 typedef boost::filter_iterator< TrueOnEven, int > TakeEvenFilterType;

 std::copy( 
  TakeEvenFilterType(tVec.begin(), tVec.end()),
  TakeEvenFilterType(tVec.end(), tVec.end()),
  std::back_inserter(tOtherVec));
}

To be honest, this is anything else than nice and intuitive. I wrote a simple "Enumerator" library including lazy integrated queries to avoid hotchpotch like the above. It allows you to write:

Query::From(tVec.begin(), tVec.end())
.Skip<2>()
.ToStlSequence(std::back_inserter(tOtherVec));

where Skip<2> basically instantiates a generalized "Filter" which skips every N-th (in this case every second) element.

like image 23
Paul Michalik Avatar answered Nov 15 '22 14:11

Paul Michalik