2d向量的迭代器

时间:2009-11-23 17:09:33

标签: c++ stl vector iterator

如何为2d向量(向量向量)创建迭代器/?

8 个答案:

答案 0 :(得分:39)

虽然你的问题非常清楚,但我假设你的意思是指一个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 ...
    }
}

答案 1 :(得分:9)

您可以使用range for语句迭代二维向量中的所有元素。

vector< vector<int> > vec;

让我们假设你已经将很多元素推送到vec;

for(auto& row:vec){
   for(auto& col:row){
      //do something using the element col
   }
}

答案 2 :(得分:6)

解释这个问题的另一种方法是,你希望在vector<vector<>>上使用1D迭代器将其提供给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()一起使用,因为这需要随机访问迭代器。您可以将其设置为随机访问迭代器,但您必须在开始时扫描向量,以便可以在固定时间内将平面索引映射到idxOuteridxInner。不是完全无足轻重,但也不难。

答案 3 :(得分:1)

自2020年以来,我将发布一种更新且简便的方法。在撰写本文时,适用于c ++ 11及更高版本。 请参见以下示例,其中将2D向量(向量的向量)的元素(此处为:元组 <字符串,大小_t> )与另一个值()进行比较> string query ),然后该函数将返回匹配的第一个元素,或指示“未找到”。

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);
}

这里是一个没有元组的例子:

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  "";
}

答案 4 :(得分:0)

假设您的意思是STL迭代器,以及实现通用2D对象数组的自定义容器,这是不可能的。 STL迭代器仅支持递增和递减(即“下一个”“前一个”)操作,其中通过2D集的运动需要四个这样的基元(例如,左/右/上/下等......)。隐喻不匹配。

你想做什么?

答案 5 :(得分:0)

假设你的意思是向量的向量,并且考虑到std::vector,那么没有内置的方法可以做到这一点,因为迭代器只支持递增和递减操作来向前和向后移动。

2D向量是一个矩阵,因此您需要两种迭代器类型:行迭代器和列迭代器。行迭代器将“向上”和“向下”移动矩阵,而列迭代器将“向左”和“向右”移动。

你必须自己实现这些迭代器类,这不一定是一件微不足道的事情。当然,除非您只是想迭代矩阵中的每个槽,在这种情况下,使用索引变量ij的双循环将正常工作。根据您的需要(您的帖子内容有点缺乏),您可能需要使用boost::numeric::ublas::matrix,它是Boost线性代数库中的矩阵类。这个矩阵类有内置的行和列迭代器,这使得它通常很容易迭代矩阵。

答案 6 :(得分:0)

假设您有一个像这样的向量:-

    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
  }



其他更短的方法是

 for(auto i : vect)
  {
     for(auto j : i)
        cout << j <<" ";
     cout << "\n";
//similarly you can do other things also.
  }



请注意,两种情况下调用变量的方式都是不同的。

答案 7 :(得分:0)

在这种情况下,您可以使用自动关键字:

#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;
}