[英]How do I iterate over a vector and also know the index of the element?
我需要访问向量中的每个元素,还需要知道元素所在的索引。
到目前为止,我可以想出两种方法
for (iterator it= aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)
留下类型签名。 看起来我也不能使用自动
for (int index = 0; index < aVector.size(); ++index)
{
// access using []
}
哪个更有效或者有更好的方法来做到这一点?
对于向量或其他随机访问容器,它几乎没有区别。 我可能会选择第二个,因为它更容易阅读,而且可能稍微快一点,因为只有一个循环变量要更新。 另一种选择是:
for (auto it = aVector.begin(); it != aVector.end(); ++it) {
int index = std::distance(aVector.begin(), it);
}
对于非随机访问的容器, []
不可用,并且std::distance
效率低下; 在这种情况下,如果您需要索引,第一种方法会更好(尽管您需要修复它,以便它不会尝试在 for-initialiser 中声明两个不同类型的变量)。
答案就在问题中—— “知道元素在哪个索引中。” .
所以 -
for (int index = 0; index < aVector.size(); ++index)
{
// access using []
}
在性能方面它们是相同的(但您始终可以对自己进行配置)。
其他方式。
int count = 0;
for (auto& it : aVector) {
count++;
}
这是使用zip_iterator
库中的zip_iterator
和counting_iterator
的解决方案。 这可能是矫枉过正的方式为你的使用情况,但它与任何工作范围(不仅是矢量),并与标准的算法基于迭代器的设计很好地适应它,所以我在这里发布的优点:
#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';
}
您可以使用 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";
遗憾的是,由于index
是迭代器方法的一部分,这意味着您不能使用新的基于范围的 for 循环,甚至BOOST_FOREACH
,它只提供元素访问权限。 这是一个相当样板的价值可疑的解决方法:
// 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:
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++ 老派:
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)
这不会编译。 但这并不重要,因为只要我们在谈论std::vector
那么通过索引访问就是一个简单的指针算术和解引用——所以实际上和迭代器一样快。 所以你的版本 2 没问题。
然而,我会进一步优化(如果你真的很关心速度):
for (int index = 0, size = aVector.size(); index < size; ++index)
{
// access using []
}
有点悬而未决,由于逗号运算符的工作方式,OP 的第一条语句无法编译。 我确定 OP 只是使用iterator
的简写而不是完整的类型名,但这不是问题:
for (iterator it= aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)
逗号运算符要么分隔两个表达式(并返回第二个表达式的结果),要么用于分隔声明中的变量。 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.