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
, andgreater_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: Ifa < b
is well-defined for pointersa
andb
of typeP
, 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
Have You Used Any of the C++ Interpreters (Not Compilers)
How to Use a Custom Deleter With a Std::Unique_Ptr Member
How to Include Libraries in Visual Studio 2012
How to Efficiently Select a Standard Library Container in C++11
Using a C++ Class Member Function as a C Callback Function
When Are C++ Macros Beneficial
How to Link Opencv in Qtcreator and Use Qt Library
Why Will Std::Sort Crash If the Comparison Function Is Not as Operator ≪
C++: Print Out Enum Value as Text
C++ Code File Extension? Difference Between .Cc and .Cpp
How to Render Offscreen on Opengl
Why Would the Behavior of Std::Memcpy Be Undefined For Objects That Are Not Triviallycopyable
How to Install the Raspberry Pi Cross Compiler on My Linux Host Machine
Why Do People Use _ (Double Underscore) So Much in C++
Virtual Function Default Arguments Behaviour
How to Sort Two Vectors in the Same Way, With Criteria That Uses Only One of the Vectors