How to Get the Index of an Iterator of an Std::Vector

How do I get the index of an iterator of an std::vector?

I would prefer it - vec.begin() precisely for the opposite reason given by Naveen: so it wouldn't compile if you change the vector into a list. If you do this during every iteration, you could easily end up turning an O(n) algorithm into an O(n^2) algorithm.

Another option, if you don't jump around in the container during iteration, would be to keep the index as a second loop counter.

Note: it is a common name for a container iterator,std::container_type::iterator it;.

C++ turn vector iterator into index

The range-based for loop

for (range_declaration : range_expression) 
loop_statement

is roughly equivalent to this code:

for (auto begin = range_expression.begin(), end = range_expression.end(); 
begin != end; ++begin)
{
range_declaration = *begin;
loop_statement
}

Note the * operator. So, range_declaration is not the iterator, but an element, it points to.

If you need an index, use plain for loop:

for (std::size_t index = 0; index < my_vector.size(); ++index)
loop_statement

Index of vector iterator

If by 'ID' you mean index, use

i - vec.begin()

C++ STL Vectors: Get iterator from index?

Try this:

vector<Type>::iterator nth = v.begin() + index;

Rgd: Vector Iterator to get Index Position

You have a vector of objects. Each object contains an int. You're trying to "find" the object in that vector which has a given value in that int. But the compiler doesn't understand this, because the STL only describes how to find values in containers. And how could it be otherwise? If you had an object containing two ints, which one would be compared?

Since you said the use of std::find() was for better performance than the old-school for-loop, you can stop trying now and just go back to that. The performance will be basically the same either way, and you said already that you're out of time. So just use what you had working, because it's not a performance problem.

If you insist on using iterators, you could use std::find_if() with a custom predicate you'd define, like this:

struct HasId {
HasId(int id) : _id(id) {}
bool operator()(node const& n) const { return n.nodeid == _id; }
private:
int _id;
}

std::find_if(cNode.begin(), cNode.end(), HasId(id));

This way, we have provided enough information to let the STL find the element we're interested in, without creating a temporary node to search for.

Getting Index in a vector via interators

No, you don't have to implement any operator. The problem is that you use two different types of iterators, iterator and reverse_iterator. You can always access the normal iterator pointing at the next element using base().

return it.base() - vec.begin() - 1;

Finding the index when using a vector<>::iterator

myIndex = iter - myStringVec.begin();

or

myIndex = std::distance(myStringVec.begin(), iter);

Also note that to be portable (and possibly to eliminate compiler warnings), myIndex should be of type std::vector<std::string>::difference_type rather than int.

How to get the index of an element of a std::vector from the reference to one of it's items?

This does the trick:

template <class T>
std::size_t GetIndexFromRef(std::vector<T> const &vec, T const &item)
{
T const *data = vec.data();

if(std::less<T const *>{}(&item, data) || std::greater_equal<T const *>{}(&item, data + vec.size()))
throw std::out_of_range{"The given object is not part of the vector."};

return static_cast<std::size_t>(&item - vec.data());
};

I'm using std::less and std::greater_equal, because ([comparisons.general§2]):

For templates less, greater, less_­equal, and greater_­equal, the specializations for any pointer type yield a result consistent with the implementation-defined strict total order over pointers ([defns.order.ptr]).

[Note 1: If a < b is well-defined for pointers a and b of type P, then (a < b) == less<P>()(a, b), (a > b) == greater<P>()(a, b), and so forth.
end note]

Otherwise, performing the comparison with an object that isn't part of the vector would be UB.

Get index in vector from reverse iterator

I would use:

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
auto v = std::vector<int> { 1, 2, 3 };
auto rit = std::find(v.rbegin(), v.rend(), 3);
if (rit != v.rend()) {
auto idx = std::distance(begin(v), rit.base()) - 1;
std::cout << idx;
} else
std::cout << "not found!";
}

Live Example.

The reason for the -1 in the distance computation is because of the conversion between reverse and regular iterators in the .base() member:

24.5.1 Reverse iterators [reverse.iterators]

1 Class template reverse_iterator is an iterator adaptor that iterates
from the end of the sequence defined by its underlying iterator to the
beginning of that sequence. The fundamental relation between a reverse
iterator and its corresponding iterator i is established by the
identity: &*(reverse_iterator(i)) == &*(i - 1).

Note: you could also use the above code without the check for v.rend(), and use the convention that idx == -1 is equivalent to an element that is not found. However, that loses the ability to do v[idx], so eventually you would need a check against that as well.



Related Topics



Leave a reply



Submit