Обратная итерация с 2 циклами? - PullRequest
2 голосов
/ 09 августа 2010

В основном я хочу выполнить обратную итерацию через 2 std :: vectors. слой имеет вектор форм.

обычно я мог бы сделать что-то вроде этого:

for(int i = 0; i < layers.size(); ++i)
{
   for(int j = 0; j < layers[i].shapes.size(); ++j)
   {
      layers[i].shapes[j].dosomething();
   }
}

Однако сейчас мне нужно выполнить обратную итерацию по векторам, и поэтому мне нужно использовать обратный итератор, но как это будет работать? Поскольку итераторы как бы делают его похожим на a для каждого, как я могу получить доступ к текущей форме текущего слоя, через который выполняется итерация? Спасибо

Ответы [ 7 ]

5 голосов
/ 09 августа 2010

Простой способ:

for(int i = layers.size() - 1; i >= 0; --i)
{
   for(int j = layers[i].shapes.size() - 1; j >= 0; --j)
   {
      layers[i].shapes[j].dosomething();
   }
}

«Правильный» путь:

for(vector<Layer>::reverse_iterator i = layers.rbegin(); i != layers.rend(); ++i)
{
   for(vector<Shape>::reverse_iterator j = i->shapes.rbegin(); j != i->shapes.rend(); ++j)
   {
      j->dosomething();
   }
}
1 голос
/ 09 августа 2010

Используйте обратные итераторы.

typedef std::vector::<Layer>::reverse_iterator LayerIt;
for(LayerIt layerIt = layers.rbegin(); layerIt != layers.rend(); ++layerIt) // reverse-iterator
{
   Layer& layer = *layerIt;

   typedef std::vector<Shape>::reverse_iterator ShapeIt;
   std::vector<Shape>& shapes = layer.shapes;

   for(ShapeIt shapeIt = shapes.rbegin(); shapeIt != shapes.rend(); ++shapeIt) // reverse-iterator
   {
     Shape& shape = *shapeIt;
     shape.dosomething();
    }
}

См. Функции rbgin () и rend () в std :: vector: http://www.cplusplus.com/reference/stl/vector/ Я разложил код, чтобы сделать его более очевидным, скажите мне, если это не так. Если вы не знаете об итераторах, вам придется искать:)

Обратите внимание, что если вы используете недавний компилятор с новыми auto функциями, проще написать:

for(auto layerIt = layers.rbegin(); layerIt != layers.rend(); ++layerIt) // reverse-iterator
{
   Layer& layer = *layerIt;
   std::vector<Shape>& shapes = layer.shapes;

   for(auto shapeIt = shapes.rbegin(); shapeIt != shapes.rend(); ++shapeIt) // reverse-iterator
   {
     Shape& shape = *shapeIt;
     shape.dosomething();
    }
}
0 голосов
/ 09 августа 2010

Итераторы для контейнеров позволяют вам получить доступ к «текущему» объекту с помощью операторов * или -> - в этом смысле итераторы подобны указателям на элементы вектора.

Например, если iter - этоитератор для вектора слоев, затем вы можете получить доступ к слою, указанному в данный момент итератором, используя:

layer = *(iter);

или

nshapes = iter->shapes.size();
0 голосов
/ 09 августа 2010

Вы также можете использовать обратные итераторы, но это немного многословно. Если у вас есть Boost, это действительно легко, так как вы можете сделать что-то вроде:

BOOST_REVERSE_FOREACH( std::vector<Shape>& layer, layers )
{
  BOOST_REVERSE_FOREACH( Shape& shape, layer )
  {
    shape.dosomething();
  }
}
0 голосов
/ 09 августа 2010
for(std::vector<mytype>::reverse_iterator i = layers.rbegin(); i != layers.rend(); ++i)
{
   for(std::vector<myothertype>::reverse_iterator j = i->shapes.rbegin(); j != i->shapes.rend(); ++j)
   {
      j->dosomething();
   }
}

Итераторы более гибки, чем основанные на индексах - гораздо проще изменить начало / rbegin, конец / rend и reverse_iterator / iterator, чтобы изменить направление итерации. Это становится еще проще, если вы часто используете этот код и можете просто вставить где-нибудь typedef, и определенно лучше, если у вас есть C ++ 0x или вы можете использовать встроенную функцию для автоматического вывода типа.

0 голосов
/ 09 августа 2010

Вам не нужны итераторы (обратные или нет) для этого. Если вам нравится код, который у вас есть прямо сейчас, и вы хотите, чтобы он работал в обратном порядке, вы можете сделать это довольно напрямую:

for (int i=layers.size()-1; i>-1; --i)
    for (int j=layers[i].shapes.size()-1; j>-1; --j)
        layers[i].shapes[j].dosomething();

Конечно, вы можете использовать итераторы, если хотите, но в этом случае я думаю, что это сделает код длиннее и сложнее в целом, без большого добавления:

std::vector<shape>::reverse_iterator this_shape;
std::vector<layer>::reverse_iterator this_layer;

for (this_layer = layers.rbegin(); this_layer != layers.rend(); ++this_layer)
   for (this_shape = this_layer->shapes.rbegin(); this_shape != this_layer->shapes.rend(); ++this_shape)
       this_shape->dosomething();
0 голосов
/ 09 августа 2010

Если вы используете индексы для прямой итерации, почему не для обратной? то есть

for( int i = layers.size()-1; i>=0; --i )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...