如何为二维向量(即内含向量的向量)创建迭代器?
虽然你的问题不是很清楚,但我会假设你指的是2D向量表示向量的向量:
vector< vector<int> > vvi;
那么您需要使用两个迭代器来遍历它,第一个是“行”的迭代器,第二个是该“行”中“列”的迭代器:
//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 ...
}
}
*col[0]
和 *col[1]
吗? - Austin Hyde你可以使用range for语句来迭代二维向量中的所有元素。
vector< vector<int> > vec;
假设你已经将许多元素 push_back 到 vec 中;
for(auto& row:vec){
for(auto& col:row){
//do something using the element col
}
}
解释这个问题的另一种方式是,您想要一个1D迭代器来遍历vector<vector<>>
,例如将其提供给for_each()
或其他算法。
您可以按照以下方式实现:
#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";
}
}
输出:
{ -100 100 -5 -3 }
{ -4 -1 6 2 }
{ 5 }
{ 3 }
请注意,这不适用于std::sort()
,因为它需要随机访问迭代器。你可以将其变成随机访问迭代器,但必须在开始时扫描向量,以便您可以在常数时间内从平面索引映射到idxOuter
和idxInner
。这并不完全简单,但也不难。
const_iterator
? 存储索引而不是向量迭代器有特定的原因吗? 顺便说一句,我花了一段时间才理解这个例子,因为输出使用“正常”迭代器,而1D迭代器的使用在这个看似无害的reverse
行中有点隐藏。 - 463035818_is_not_a_numberconst_iterator
版本。它更多或更少地是一个复制/粘贴,将非const成员删除(我找不到避免复制/粘贴的方法)。好吧,我想没有理由不使用向量迭代器。那可能更好,我只是没想到。 - Timmmmvector <vector<int>> vect{{1,2,3},{4,5,6},{7,8,9}};
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
}
for(auto i : vect)
{
for(auto j : i)
cout << j <<" ";
cout << "\n";
//similarly you can do other things also.
}
既然已经到了2020年,我将发布一种更新且简单的方法。截至撰写本文时,适用于c++11及以上版本。 请参考以下示例,其中对2D向量(向量的向量)的元素(这里是<string,size_t>元组)进行迭代以与另一个值(字符串查询)进行比较,然后函数返回第一个匹配的元素,或指示“未找到”。
tuple<string, size_t> find_serial_data( vector <vector <tuple <string, size_t>>> &serial,
string query)
{
for (auto& i : serial)
{
for (auto& j : i)
{
if ( get<0>(j).compare(query) == 0) return j;
}
}
cout << "\n Not found";
return make_tuple( "", 0);
}
Here is one example without the tuple thing:
string find_serial_data( vector <vector <string> > &serials,
string query)
{
for (auto& i : serials)
{
for (auto& j : i)
{
if ( j.compare(query) == 0) return j;
}
}
cout << "\n Not found";
return "";
}
#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;
}
假设您指的是向量的向量,并且您考虑使用std::vector
,那么没有内置的方法可以实现,因为迭代器只支持增加和减少操作以向前和向后移动。
二维向量是矩阵,因此您需要两种迭代器类型:行迭代器和列迭代器。 行迭代器将在矩阵上“上下”移动,而列迭代器将在矩阵上“左右”移动。
您必须自己实现这些迭代器类,这并不一定是一件简单的事情。 除非您只想迭代矩阵中的每个插槽,在这种情况下,使用索引变量i
和j
的双重循环将完美地工作。 根据您的需求(您的帖子在此内容方面有点缺乏),您可能希望使用boost::numeric::ublas::matrix
,这是来自Boost线性代数库的矩阵类。 这个矩阵类具有内置的行和列迭代器,使得通常很容易迭代矩阵。