C++ 如何迭代向量并知道元素的索引?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12495382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I iterate over a vector and also know the index of the element?
提问by unj2
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?
哪个更有效或者有更好的方法来做到这一点?
采纳答案by Mike Seymour
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; 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).
对于非随机访问的容器,[]
不可用且std::distance
效率低下;在这种情况下,如果您需要索引,第一种方法会更好(尽管您需要修复它,以便它不会尝试在 for-initialiser 中声明两个不同类型的变量)。
回答by Luchian Grigore
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).
在性能方面它们是相同的(但您始终可以对自己进行配置)。
回答by Luc Touraille
Here is a solution using zip_iterator
and counting_iterator
from the Boost.Iterator library. It is probably wayoverkill 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:
这是使用zip_iterator
和counting_iterator
来自Boost.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';
}
回答by Xeo
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
适配器,它使用index
返回当前索引 (duh)的方法扩展范围的迭代器。
#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. Here's a rather boilerplate-y workaround of questionable value:
可悲的是,由于它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";
回答by matiu
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;
}
回答by Fiktik
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. So your version 2 is OK.
这不会编译。但这并不重要,因为只要我们在谈论,std::vector
通过索引访问就是一个简单的指针算术和解引用——所以实际上和迭代器一样快。所以你的版本 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 []
}