[英]How do I iterate over a vector and also know the index of the element?
I need to access each element in a vector and also know what index the element is in.我需要访问向量中的每个元素,还需要知道元素所在的索引。
So far I could come up with two ways到目前为止,我可以想出两种方法
for (iterator it= aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)
leaving the type signature.留下类型签名。 also it looks like i can't use auto看起来我也不能使用自动
for (int index = 0; index < aVector.size(); ++index)
{
// access using []
}
Which one is more efficient or is there a better way to do this?哪个更有效或者有更好的方法来做到这一点?
For a vector or other random-access container, it makes little difference.对于向量或其他随机访问容器,它几乎没有区别。 I would probably choose the second because it's easier to read, and is probably marginally faster since there's only one loop variable to update.我可能会选择第二个,因为它更容易阅读,而且可能稍微快一点,因为只有一个循环变量要更新。 Another alternative is:另一种选择是:
for (auto it = aVector.begin(); it != aVector.end(); ++it) {
int index = std::distance(aVector.begin(), it);
}
For non-random-access containers, []
isn't available, and std::distance
is inefficient;对于非随机访问的容器, []
不可用,并且std::distance
效率低下; in that case, if you need the index, the first method would be better (although you'll need to fix it so it doesn't try to declare two differently-typed variables in the for-initialiser).在这种情况下,如果您需要索引,第一种方法会更好(尽管您需要修复它,以便它不会尝试在 for-initialiser 中声明两个不同类型的变量)。
The answer is in the question - "know what index the element is in."答案就在问题中—— “知道元素在哪个索引中。” . .
So -所以 -
for (int index = 0; index < aVector.size(); ++index)
{
// access using []
}
Performance-wise they're the same (but you can always profile yourself).在性能方面它们是相同的(但您始终可以对自己进行配置)。
Another way.其他方式。
int count = 0;
for (auto& it : aVector) {
count++;
}
Here is a solution using zip_iterator
and counting_iterator
from the Boost.Iterator library .这是使用zip_iterator
库中的zip_iterator
和counting_iterator
的解决方案。 It is probably way overkill for your use case, but it has the advantages of working with any range (not only vectors) and to fit it nicely with the iterator-based design of standard algorithms, so I post it here:这可能是矫枉过正的方式为你的使用情况,但它与任何工作范围(不仅是矢量),并与标准的算法基于迭代器的设计很好地适应它,所以我在这里发布的优点:
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <algorithm>
#include <iostream>
#include <list>
int main()
{
typedef std::list<int> container;
typedef boost::tuple<
container::iterator,
boost::counting_iterator<container::size_type>
> tuple_type;
typedef boost::zip_iterator<tuple_type> it_type;
container l{1, 2, 3, 4};
it_type begin(tuple_type(l.begin(), 0));
it_type const end(tuple_type(l.end(), l.size()));
// sample use with for loop
for (it_type it = begin; it != end ; ++it)
{
int value = it->get<0>();
int index = it->get<1>();
// do whatever you want with value and index
}
// sample use with standard algorithm
auto res = std::find_if(begin, end,
[](boost::tuple<int, int> const & t)
{ return t.get<0>() > 2; }); // find first element greater than 2
std::cout << "Value: " << res->get<0>() << '\n' <<
"Index: " << res->get<1>() << '\n';
}
You can use Boost.Range's indexed
adaptor, which extends the range's iterators with an index
method that returns the current index (duh).您可以使用 Boost.Range 的indexed
适配器,它使用返回当前索引 (duh) 的index
方法扩展范围的迭代器。
#include <boost/range/adaptor/indexed.hpp>
// ...
auto&& r = vec | boost::adaptors::indexed(0);
for(auto it(begin(r)), ite(end(r)); it != ite; ++it)
std::cout << it.index() << ": " << *it << "\n";
Sadly, since index
is part a method on the iterator, this means you can't use the new range-based for loop or even BOOST_FOREACH
, which only give element access.遗憾的是,由于index
是迭代器方法的一部分,这意味着您不能使用新的基于范围的 for 循环,甚至BOOST_FOREACH
,它只提供元素访问权限。 Here's a rather boilerplate-y workaround of questionable value:这是一个相当样板的价值可疑的解决方法:
// note: likely contains typos or bugs
#include <boost/range/adaptors.hpp>
template<class IndexIt>
auto pair_index_value(IndexIt it)
-> std::pair<std::size_t, decltype(*it)>
{
return std::pair<std::size_t, decltype(*it)>(it.index(), *it);
}
// ...
using namespace boost::adaptors;
auto&& ir = vec | indexed; // because screw you Boost.Range
for(auto&& elem : boost::counting_range(ir.begin(), ir.end()) | transformed(pair_index_value))
std::cout << elem.first << ": " << elem.second << "\n";
c++11: C++11:
for (auto i=aVector.begin(); i!=aVector.end(); ++i) {
cout << "I am at position: " << i-aVector.begin() << endl;
cout << "contents here is: " << *i << endl;
}
c++ old school: C++ 老派:
for (vector<int>::const_iterator i=aVector.begin(); i!=aVector.end(); ++i) {
cout << "I am at position: " << i-aVector.begin() << endl;
cout << "contents here is: " << *i << endl;
}
for (iterator it = aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)
This will not compile.这不会编译。 But it doesn't really matter, because as long as we are talking about std::vector
then accessing by index is a simple pointer arithmetic and dereference - so in reality as fast as with the iterator.但这并不重要,因为只要我们在谈论std::vector
那么通过索引访问就是一个简单的指针算术和解引用——所以实际上和迭代器一样快。 So your version 2 is OK.所以你的版本 2 没问题。
I would however further optimize (if you are really concerned about speed):然而,我会进一步优化(如果你真的很关心速度):
for (int index = 0, size = aVector.size(); index < size; ++index)
{
// access using []
}
To be a little pendantic, the OP's first statement doesn't compile because of the way the comma operator works.有点悬而未决,由于逗号运算符的工作方式,OP 的第一条语句无法编译。 I'm sure the OP was just using a shorthand for iterator
instead of the full typename, but that isn't the problem:我确定 OP 只是使用iterator
的简写而不是完整的类型名,但这不是问题:
for (iterator it= aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)
The comma operator either separates two expressions (and returns the result of the second expression), or it is used to separate variables in a declaration.逗号运算符要么分隔两个表达式(并返回第二个表达式的结果),要么用于分隔声明中的变量。 The first argument of the for argument will take either form, so it is obfuscates the fact that they are different syntaxes. for 参数的第一个参数将采用任何一种形式,因此混淆了它们是不同语法的事实。
#include <vector>
#include <iostream>
int main()
{
std::vector<int> aVector = {1,1,2,3,5,8,13};
// option 1. Both loop variables declared outside the for statement, initialized inside the for statement
int index1 = 0;
decltype(aVector.begin()) it1;
for (it1 = aVector.begin(), index1=0; it1!= aVector.end(); ++it1, ++index1)
{
std::cout << "[" << index1 << "]=" << *it1 << std::endl;
}
// option 2. The index variable declared and initialized outside, the iterator declared and initialized inside
int index2=0;
for (auto it2 = aVector.begin(); it2!= aVector.end(); ++it2, ++index2)
{
std::cout << "[" << index2 << "]=" << *it2 << std::endl;
}
#if 0
// option3 (the OP's version) won't compile. The comma operator doesn't allow two declarations.
for (auto it3 = aVector.begin(), int index3=0 ; it3!= aVector.end(); ++it3, ++index3)
{
std::cout << "[" << index3 << "]=" << *it3 << std::endl;
}
#endif
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.