check if second to last in an iterator - c++

Is there a clean way to check if I am currently at the second to last element in an iteration in C++? As in:
for (vector::iterator it = v.begin(); it < v.end(); ++it)
{
if (it points to second to last element)
cout << "at second to last";
}

The easiest way would be to compare your iterator against one which does indeed point to the second-to-last. And an easy way to get that is:
vector::iterator secondLast = v.end() - 2;
Assuming of course that v.size() >= 2. But the above doesn't generalize to other container types, for which you could do this:
vector::iterator secondLast = (++v.rbegin()).base();
This should rewind from the last element one step, then convert to a regular (forward) iterator. This will work with other container types like lists.
Or perhaps clearer for the general solution:
vector::iterator secondLast = v.end();
std::advance(secondLast, -2);
Again this requires size of 2 and iterators of random access or bidirectional type.
And finally, a C++11 solution:
auto secondLast = std::prev(v.end(), 2);

Try something like this:
vector::iterator end = v.end(), stl;
bool has_stl = (v.size() >= 2);
if (has_stl) stl = end-2;
for (vector::iterator it = v.begin(); it < end; ++it)
{
if ((has_stl) && (it == stl))
cout << "at second to last";
}

You can do this with some containers:
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec {1, 2, 3, 4, 5};
for (auto it = vec.begin(); it != vec.end(); it++) {
if (vec.end() - it == 3) {
std::cout << *it << std::endl;
}
}
return 0;
}

A solution below:
auto pos = std::next(std::begin(v), std::distance(std::begin(v), std::end(v))-2);
for (auto it = std::begin(v); it != std::end(v); ++it)
{
if (it == pos)
cout << "at second to last: " << *pos;
}
pos is now an iterator pointing to the second to last position, and the functions std::next and std::distance use the best implementation possible (i.e. constant complexity for random iterators, linear complexity for bidirectional/forward iterators).

Related

Detect equal elements in a std::list

Is there a better way of finding elements of a std::list that have the same value as manually going over the sorted list and comparing each element like this:
for(auto it = l.begin(); it != l.end(); it++) {
auto nextElement = it;
nextElement++;
if(nextElement == l.end())
break;
if(*it == *nextElement)
cout << "Equal" << endl;
}
There is actually a really nice and compact way to get a list of all of the duplicates in a set of data, whether it is sorted or not. What we can do is leverage std::map/std::unordered_map and use the elements value as the key for the map, and make the value a count of the number of times that value was "inserted". That would look like
std::unordered_map<int, int> histogram;
for (auto e : l)
++histogram[e]; // gets a count of the number of duplicates
and then all you need to do is iterate the map and check for entries that have a mapped value greater than 1. That would look like
for (const auto& pair : histogram)
if (pair.second > 1)
std::cout << "value: " << pair.first << " has " << pair.second << " matches.\n";
Using a std::map this is O(NlogN + M) and using an unoredered_map this is O(N + M) where N is the size of l and M is the size of histogram.
Use the STL algorithm adjacent_find:
auto it = l.begin()
while((it = std::adjacent_find(it, l.end())) != l.end()){
std::cout << "Equal\n";
++it;
}
Since you say the list is sorted, then std::adjacent_find will detect whether there are duplicates:
#include <algorithm>
if (std::adjacent_find(l.begin(), l.end()) != l.end()) {
// we have at least one duplicate
}
If you wish to do something with all the duplicates, then we can loop over the pairs:
for (auto it = std::adjacent_find(l.begin(), l.end());
it != l.end();
it = std::adjacent_find(std::next(it), l.end())
{
// *it and *std::next are duplicates (and there may be more)
}
It's possible that we want to find and process all of each group of identical elements together:
auto begin = std::adjacent_find(l.begin(), l.end());
while (begin != l.end()) {
auto end = std::find_if_not(begin, l.end(),
[begin](auto n){ return n == *begin;});
// All elements from begin (inclusive) to end (exclusive) are equal.
// Process them here.
begin = std::adjacent_find(end, l.end());
}

how to print vector of vectors using vector.begin() to vector.end()

Take a vector of vector of int's how do I print all of them from begin to end
for(row=v.begin();row!=v.end();row++){
for(col=row->begin();col!=row->end();col++){
//cout<<?
}
}
What should be used in inner for loop to print each element
Personally, I like iterating over vectors just using a simple for loop from 0 to size(), but this is how you would do it with iterators:
for(vector< vector<int> >::iterator row = v.begin(); row != v.end(); ++row) {
for(vector<int>::iterator col = row->begin(); col != row->end(); ++col) {
cout << *col;
}
}
See: Iteration over std::vector: unsigned vs signed index variable
v.begin() returns an iterator to the beginning of the sequence
v.end() returns an iterator to the element past the end of the sequence
You can loop through your structure using those iterators:
for(auto it_row =v.begin(); it_row!=v.end(); it_row++){
for(auto it_col=it_row->begin();it_col!=it_row->end();it_col++){
cout<<*it_col<<endl;
}
}
In order to deference (get the value) your iterator you need to use the following syntax: *it_col
I used auto (C++ 11) instead of explicitly putting the iterator type:
vector<vector<int>>::const_iterator it_row = v.begin()
vector<int>::const_iterator it_col = it_row->begin()
You can find more details about iterators here.
If you are using c++11 then, you can use range based for loop;
for (const auto & items : v)
for (const auto & item : items)
cout << item;

Iterating through a set

I have a set of ints set something; of length 52.
I am using cycles to iterate through the set like this:
for(iterator A from 1st to 48th element)
for(iterator B from A+1 to 49th element)
for(iterator C from B+1 to 50th element)
for(iterator D from C+1 to 51th element)
for(iterator E from D+1 to 52th element)
{
//save the values from the actual positions in set in array[5]
}
First I tried to make it with an iterator but then I realised that it's not possible to start an iterator from the position of another iterator +1.
Then I tried to use pointers and jump through the values but I correctly assigned only the first value and then I can't jump on second etc.
My code was:
set<int> tableAll;
for(int i=4; i!=52; ++i)
tableAll.insert(i);
const int * flop1 = & * tableAll.begin();
cout << * flop1 << endl;
flop1++;
cout << * flop1 << endl;
When I cout the value of pointer flop1, I get 4 and that's ok, but when I increase it and again cout on screen, I get 0, then, 49, then 0, then 1, then 0 instead 5, 6, 7, 8 and 9.
So how to iterate through my set correctly? I assume using pointers will be faster then some iterator solution.
You absolutely can iterate from an offset from another iterator:
for (auto a(std::begin(mySet)), a_end(std::prev(std::end(mySet), 4));
a != a_end; ++a)
for (auto b(std::next(a)), b_end(std::next(a_end); b != b_end; ++b)
...
In C++03, you can write next and begin for compatibility:
template<typename Iterator> Iterator next(Iterator it, int n = 1) {
std::advance(it, n);
return it;
}
template<typename Iterator> Iterator prev(Iterator it, int n = 1) {
std::advance(it, -n);
return it;
}
for (std::set<int>::const_iterator a(mySet.begin()),
a_end(std::prev(mySet.end(), 4)); a != a_end; ++a)
for (std::set<int>::const_iterator b(std::next(a)),
b_end(std::next(a_end)); b != b_end; ++b)
...
This code is not optimal as it do unneeded iterator comparisions, but works and is simply:
set<int> tableAll;
for(int i=0; i!=52; ++i)
tableAll.insert(i);
for( set<int>::iterator iA=tableAll.begin(); iA != tableAll.end(); ++iA )
for( set<int>::iterator iB=iA; ++iB != tableAll.end(); )
for( set<int>::iterator iC=iB; ++iC != tableAll.end(); )
for( set<int>::iterator iD=iC; ++iD != tableAll.end(); )
for( set<int>::iterator iE=iD; ++iE != tableAll.end(); )
{
cout<<*iA<<' '<<*iB<<' '<<*iC<<' '<<*iD<<' '<<*iE<<endl;
}
I'd suggest to copy the set to a temporary std::vector.
All operations you do in the loops are natural for a vector and O(1) (except for the loops themselves of course)
That's easier to read, to write, and should run a lot faster.

iterate an STL container not from the .begin()ing and wrap around

I have an std::vector, let's say of integers for simplicity.
std::vector<int> ivec;
ivec.push_back(1);
ivec.push_back(2);
... //omitting some push back's 3 to 99
ivec.push_back(100);
The standard way to iterate is known
std::map<int>::iterator it;
for( it = ivec.begin(); it != ivec.end(); it++ )
print();
That iteration will print 1,2,3, ... 100.
I want to traverse all vector elements starting from a predefined index and not from it.begin().
I would like to print
3,4,5,6 ... 99, 100, 1, 2
Can you share your thoughts here?
It might ok to do it in two steps
for( it = ivec.begin()+index; it != ivec.end(); it++ ) and then (if index !=0)
for ( it = ivec.begin; it = it = ivec.begin() + (index-1); it++)
You can either:
develop an iterator class that wraps the vector::iterator and expose the behaviour you like (in particular: ++ checks for end() and replace it with begin() and adjust the other "border values")
fill the vector starting from 3 and wrap at 100, so that standard iteration will look as you want.
The choice depends on what else the vector is purposed and what else that iteration is needed.
I'll assume that you already have a starting iterator. How you get this depends on whether you are using an indexable (vector) type or a forward iterator only, or a keyed type. Then you can do a loop something like this:
type::iterator start_iter = /* something from collection, perhaps begin()+index */
type::iterator cur_iter = start_iter;
do
{
//do something with cur_iter
++cur_iter;
if( cur_iter == collection.end() )
cur_iter = collection.begin();
} while( cur_iter != start_iter );
That's the basic loop.
bool wrapped = false;
for (auto it = vec.begin() + index; (it != vec.begin() + index) || !wrapped; ++it)
{
if (it == vec.end())
{
it = vec.begin();
wrapped = true;
}
std::cout << *it;
}
I know this is a pretty old question, but nobody mentioned std::rotate, which I think, in some cases, can be the right tool for the job.
Modified example from http://www.cplusplus.com/reference/algorithm/rotate/:
#include <iostream> // std::cout
#include <algorithm> // std::rotate
#include <vector> // std::vector
int main () {
std::vector<int> myvector;
// set some values:
for (int i = 1; i < 10; ++i) myvector.push_back(i); // 1, 2, 3, ... 9
std::rotate(myvector.begin(), myvector.begin() + 2, myvector.end());
// 3, 4, 5, 6 ... 9, 1, 2
// print out content:
std::cout << "myvector contains:";
for (auto it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
cpp.sh/3rdru
Output:
myvector contains: 3 4 5 6 7 8 9 1 2
Note, since my_vector is modified by the std::rotate function, this is neither very efficient nor useful if you just want to iterate the vector once.
However, while this is probably not the best answer to this SO question, I hope it can still provide some value for people with similar issues.
A solution when using a random-access container is very simple, see the code below.
std::vector<int> v ({1,3,4,5,6,7,8,9,10}); /* c++11 */
...
for (int i = 2; i < (10+2); ++i)
std::cout << v[i % 10] << " ";
Method when using containers only having bidirectional/forward iterators:
std::list<int> l ({1,3,4,5,6,7,8,9,10}); /* c++11 */
Iter start = l.begin ();
std::advance (start, 4);
...
Iter it = start;
do {
std::cerr << *it << std::endl;
} while (
(it = ++it == l.end () ? l.begin () : it) != start
);
There are endless ways to do it, and probably all are (more or less) equivalent, so in the end it depends on personal preference and maybe coding style conventions. I would probably do it like:
std::cout << v[idx] << "\n";
for( auto it = v.begin() + idx + 1; it != v.begin()+idx; ++it )
{
if( it == v.end() ) it = v.begin();
std::cout << *it << "\n";
}

How to navigate through a vector using iterators? (C++)

The goal is to access the "nth" element of a vector of strings instead of the [] operator or the "at" method. From what I understand, iterators can be used to navigate through containers, but I've never used iterators before, and what I'm reading is confusing.
If anyone could give me some information on how to achieve this, I would appreciate it. Thank you.
You need to make use of the begin and end method of the vector class, which return the iterator referring to the first and the last element respectively.
using namespace std;
vector<string> myvector; // a vector of stings.
// push some strings in the vector.
myvector.push_back("a");
myvector.push_back("b");
myvector.push_back("c");
myvector.push_back("d");
vector<string>::iterator it; // declare an iterator to a vector of strings
int n = 3; // nth element to be found.
int i = 0; // counter.
// now start at from the beginning
// and keep iterating over the element till you find
// nth element...or reach the end of vector.
for(it = myvector.begin(); it != myvector.end(); it++,i++ ) {
// found nth element..print and break.
if(i == n) {
cout<< *it << endl; // prints d.
break;
}
}
// other easier ways of doing the same.
// using operator[]
cout<<myvector[n]<<endl; // prints d.
// using the at method
cout << myvector.at(n) << endl; // prints d.
In C++-11 you can do:
std::vector<int> v = {0, 1, 2, 3, 4, 5};
for (auto i : v)
{
// access by value, the type of i is int
std::cout << i << ' ';
}
std::cout << '\n';
See here for variations: https://en.cppreference.com/w/cpp/language/range-for
Typically, iterators are used to access elements of a container in linear fashion; however, with "random access iterators", it is possible to access any element in the same fashion as operator[].
To access arbitrary elements in a vector vec, you can use the following:
vec.begin() // 1st
vec.begin()+1 // 2nd
// ...
vec.begin()+(i-1) // ith
// ...
vec.begin()+(vec.size()-1) // last
The following is an example of a typical access pattern (earlier versions of C++):
int sum = 0;
using Iter = std::vector<int>::const_iterator;
for (Iter it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
The advantage of using iterator is that you can apply the same pattern with other containers:
sum = 0;
for (Iter it = lst.begin(); it!=lst.end(); ++it) {
sum += *it;
}
For this reason, it is really easy to create template code that will work the same regardless of the container type.
Another advantage of iterators is that it doesn't assume the data is resident in memory; for example, one could create a forward iterator that can read data from an input stream, or that simply generates data on the fly (e.g. a range or random number generator).
Another option using std::for_each and lambdas:
sum = 0;
std::for_each(vec.begin(), vec.end(), [&sum](int i) { sum += i; });
Since C++11 you can use auto to avoid specifying a very long, complicated type name of the iterator as seen before (or even more complex):
sum = 0;
for (auto it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
And, in addition, there is a simpler for-each variant:
sum = 0;
for (auto value : vec) {
sum += value;
}
And finally there is also std::accumulate where you have to be careful whether you are adding integer or floating point numbers.
Vector's iterators are random access iterators which means they look and feel like plain pointers.
You can access the nth element by adding n to the iterator returned from the container's begin() method, or you can use operator [].
std::vector<int> vec(10);
std::vector<int>::iterator it = vec.begin();
int sixth = *(it + 5);
int third = *(2 + it);
int second = it[1];
Alternatively you can use the advance function which works with all kinds of iterators. (You'd have to consider whether you really want to perform "random access" with non-random-access iterators, since that might be an expensive thing to do.)
std::vector<int> vec(10);
std::vector<int>::iterator it = vec.begin();
std::advance(it, 5);
int sixth = *it;
Here is an example of accessing the ith index of a std::vector using an std::iterator within a loop which does not require incrementing two iterators.
std::vector<std::string> strs = {"sigma" "alpha", "beta", "rho", "nova"};
int nth = 2;
std::vector<std::string>::iterator it;
for(it = strs.begin(); it != strs.end(); it++) {
int ith = it - strs.begin();
if(ith == nth) {
printf("Iterator within a for-loop: strs[%d] = %s\n", ith, (*it).c_str());
}
}
Without a for-loop
it = strs.begin() + nth;
printf("Iterator without a for-loop: strs[%d] = %s\n", nth, (*it).c_str());
and using at method:
printf("Using at position: strs[%d] = %s\n", nth, strs.at(nth).c_str());