C++ 二维向量的迭代器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1784573/
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
iterator for 2d vector
提问by miroslavec
How to create iterator/s for 2d vector (a vector of vectors)?
如何为二维向量(向量的向量)创建迭代器?
回答by Austin Hyde
Although your question is notvery clear, I'm going to assume you mean a 2D vector to mean a vector of vectors:
虽然你的问题不是很清楚,但我假设你的意思是一个二维向量来表示一个向量的向量:
vector< vector<int> > vvi;
Then you need to use two iterators to traverse it, the first the iterator of the "rows", the second the iterators of the "columns" in that "row":
然后你需要使用两个迭代器来遍历它,第一个是“行”的迭代器,第二个是该“行”中“列”的迭代器:
//assuming you have a "2D" vector vvi (vector of vector of int's)
vector< vector<int> >::iterator row;
vector<int>::iterator col;
for (row = vvi.begin(); row != vvi.end(); row++) {
for (col = row->begin(); col != row->end(); col++) {
// do stuff ...
}
}
回答by ShuaiYu8
You can use range for statement to iterate all the elements in a two-dimensional vector.
您可以使用 range for 语句迭代二维向量中的所有元素。
vector< vector<int> > vec;
And let's presume you have already push_back a lot of elements into vec;
让我们假设您已经将很多元素推回了 vec;
for(auto& row:vec){
for(auto& col:row){
//do something using the element col
}
}
回答by Timmmm
Another way to interpret this question is that you want a 1D iterator over a vector<vector<>>
for example to feed it to for_each()
or some other algorithm.
解释这个问题的另一种方法是,您需要一个 1D 迭代器vector<vector<>>
,例如将其提供给for_each()
其他算法。
You can do that like this:
你可以这样做:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
// An iterator over a vector of vectors.
template<typename T>
class vv_iterator : public std::iterator<std::bidirectional_iterator_tag, T>{
public:
static vv_iterator<T> begin(std::vector<std::vector<T>>& vv) {
return vv_iterator(&vv, 0, 0);
}
static vv_iterator<T> end(std::vector<std::vector<T>>& vv) {
return vv_iterator(&vv, vv.size(), 0);
}
vv_iterator() = default;
// ++prefix operator
vv_iterator& operator++()
{
// If we haven't reached the end of this sub-vector.
if (idxInner + 1 < (*vv)[idxOuter].size())
{
// Go to the next element.
++idxInner;
}
else
{
// Otherwise skip to the next sub-vector, and keep skipping over empty
// ones until we reach a non-empty one or the end.
do
{
++idxOuter;
} while (idxOuter < (*vv).size() && (*vv)[idxOuter].empty());
// Go to the start of this vector.
idxInner = 0;
}
return *this;
}
// --prefix operator
vv_iterator& operator--()
{
// If we haven't reached the start of this sub-vector.
if (idxInner > 0)
{
// Go to the previous element.
--idxInner;
}
else
{
// Otherwise skip to the previous sub-vector, and keep skipping over empty
// ones until we reach a non-empty one.
do
{
--idxOuter;
} while ((*vv)[idxOuter].empty());
// Go to the end of this vector.
idxInner = (*vv)[idxOuter].size() - 1;
}
return *this;
}
// postfix++ operator
vv_iterator operator++(int)
{
T retval = *this;
++(*this);
return retval;
}
// postfix-- operator
vv_iterator operator--(int)
{
T retval = *this;
--(*this);
return retval;
}
bool operator==(const vv_iterator& other) const
{
return other.vv == vv && other.idxOuter == idxOuter && other.idxInner == idxInner;
}
bool operator!=(const vv_iterator &other) const
{
return !(*this == other);
}
const T& operator*() const
{
return *this;
}
T& operator*()
{
return (*vv)[idxOuter][idxInner];
}
const T& operator->() const
{
return *this;
}
T& operator->()
{
return *this;
}
private:
vv_iterator(std::vector<std::vector<T>>* _vv,
std::size_t _idxOuter,
std::size_t _idxInner)
: vv(_vv), idxOuter(_idxOuter), idxInner(_idxInner) {}
std::vector<std::vector<int>>* vv = nullptr;
std::size_t idxOuter = 0;
std::size_t idxInner = 0;
};
int main()
{
std::vector<std::vector<int>> a = {{3, 5, 2, 6}, {-1, -4, -3, -5}, {100}, {-100}};
std::reverse(vv_iterator<int>::begin(a), vv_iterator<int>::end(a));
for (const auto& v : a)
{
std::cout << "{ ";
for (auto i : v)
std::cout << i << " ";
std::cout << "}\n";
}
}
Prints:
印刷:
{ -100 100 -5 -3 }
{ -4 -1 6 2 }
{ 5 }
{ 3 }
Note this won't work with std::sort()
because that requires a random access iterator. You could make it a random access iterator but you'd have to scan the vector at the start so you can map from flat index to idxOuter
and idxInner
in constant time. Not totally trivial but not hard either.
请注意,这不起作用,std::sort()
因为这需要随机访问迭代器。你可以把它随机访问迭代器,但你必须在扫描开始时的矢量,所以你可以从平面指数,衡量idxOuter
和idxInner
在固定时间。并非完全微不足道,但也不难。
回答by tanmay001
Suppose you have a vector like this:-vector <vector<int>> vect{{1,2,3},{4,5,6},{7,8,9}};
Now to use iterators with 2D vectors :-
假设你有一个这样的向量:-vector <vector<int>> vect{{1,2,3},{4,5,6},{7,8,9}};
现在使用带有 2D 向量的迭代器:-
for(auto i = vect.begin() ; i<vect.end() ; i++)
{
for(auto j = i->begin() ; j<i->end() ; j++)
cout << *j <<" ";
cout <<"\n";
//similarly you can do other things
}
Also other shorter way is
还有其他更短的方法是
for(auto i : vect)
{
for(auto j : i)
cout << j <<" ";
cout << "\n";
//similarly you can do other things also.
}
Please note the way of calling variables is different in both the cases.
请注意,这两种情况下调用变量的方式是不同的。
回答by Prakhar Gurawa
You can use auto keyword for such cases:
您可以在这种情况下使用 auto 关键字:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
vector<vector<int>>v;
for(int i=0;i<5;i++)
{
vector<int> x={1,2,3,4,5};
v.push_back(x);
}
cout<<"-------------------------------------------"<<endl;
cout<<"Print without iterator"<<endl;
cout<<"-------------------------------------------"<<endl;
for(int i=0;i<5;i++)
{
vector<int> y=v[i];
for(int j=0;j<y.size();j++)
{
cout<<y[j]<<" ";
}
cout<<endl;
}
cout<<"-------------------------------------------"<<endl;
cout<<"Print with iterator"<<endl;
cout<<"-------------------------------------------"<<endl;
for(auto iterator=v.begin();iterator!=v.end();iterator++)
{
vector<int> y=*iterator;
for(auto itr=y.begin();itr!=y.end();itr++)
{
cout<<*itr<<" ";
}
cout<<endl;
}
return 0;
}
回答by Andy Ross
Assuming you mean an STL iterator, and a custom container that implements a generic 2D array of objects, this is impossible. STL iterators support only increment and decrement (i.e. "next" an "previous") operations, where motion through a 2D set requires four such primitives (e.g. left/right/up/down, etc...). The metaphors don't match.
假设您指的是 STL 迭代器和实现通用 2D 对象数组的自定义容器,这是不可能的。STL 迭代器仅支持递增和递减(即“下一个”和“上一个”)操作,其中通过 2D 集合的运动需要四个这样的原语(例如左/右/上/下等...)。比喻不符。
What are you trying to do?
你想做什么?
回答by Charles Salvia
Assuming you mean a vector of vectors, and you have std::vector
in mind, there's no built in way to do it, as iterators only support increment and decrement operations to move forward and backwards.
假设您的意思是向量的向量,并且您已经std::vector
记住了,没有内置的方法可以做到这一点,因为迭代器仅支持递增和递减操作来向前和向后移动。
A 2D vector is a matrix, and so you'd need two iterator types: a row iterator and a column iterator. Row iterators would move "up" and "down" the matrix, whereas column iterators would move "left" and "right".
二维向量是一个矩阵,因此您需要两种迭代器类型:行迭代器和列迭代器。行迭代器将“向上”和“向下”移动矩阵,而列迭代器将“向左”和“向右”移动。
You have to implement these iterator classes yourself, which is not necessarily a trivial thing to do. Unless, of course, you simply want to iterate over each slot in the matrix, in which case a double for loop using index variables i
and j
will work just fine. Depending on your needs (your post is a bit lacking in content here), you may want to use boost::numeric::ublas::matrix
, which is a matrix class from the Boost linear algebra library. This matrix class has built-in row and column iterators, which make it generally easy to iterate over a matrix.
您必须自己实现这些迭代器类,这不一定是一件微不足道的事情。除非,当然,你只是想每个插槽遍历矩阵中的,在这种情况下使用索引变量,双for循环i
,并j
会工作得很好。根据您的需要(您的帖子在这里有点缺乏内容),您可能需要使用boost::numeric::ublas::matrix
,它是 Boost 线性代数库中的一个矩阵类。这个矩阵类具有内置的行和列迭代器,这使得迭代矩阵通常很容易。