2010-12-14 5 views
1

Я считаю себя зацикливание над векторами векторов много:Как облегчить вложенную петлю?

std::vector<std::vector<int> > foo; 

for(unsigned int i=0; i != foo.size(); ++i) { 
for(unsigned int j=0; j != foo[i].size(); ++j) { 
    // use foo[i][j] 
} 
} 

Я не хороший минимальный пример, почему «данные» представляется лучшим вектором векторов междунар, но давайте не сомневаюсь, это здесь.

Что вы предлагаете упростить цикл? Я мог бы думать о функции, которая реализует явный цикл и принимает указатель на функцию для тела.

Как «генерировать» вложенные петли в случае большего количества уровней?

Существуют ли языки, которые имеют «встроенную» поддержку для «вложенных циклов»?

Спасибо заранее,

Кто-то

ответ

2

я мог думать о функции, которая реализует явное зацикливание и принимает указатель на функцию для тела.

Похоже шаблон для посетителей:

http://en.wikipedia.org/wiki/Visitor_pattern

редактировать:

Я не проверял часть шаблона, но что-то вроде этого:

class Visitor 
{ 
    public: 
     template<typename T> 
     void visit(const std::vector<T> &vector) 
     { 
      for(typename std::vector<T>::const_iterator it(vector.begin()); 
       it != vector.end(); 
       ++it) 
      { 
       visit(*it); 
      } 
     } 

     void visit(int i) 
     { 
      // do something with i 
     } 
} 


// usage: 
std::vector<std::vector<int> > theData; 

Visitor v; 
v.visit(theData); 
std::cout << v.result() << std::endl; 
1

Eсть нет встроенного цикла для вложенных структур (учитывая глубина гнездования может быть произвольной). У вас есть несколько вариантов.

Сгладить 2D-вектор в одномерный вектор и перебрать его или, Использовать что-то вроде for_each, например.

template <typename T> 
struct do_foo 
{ 
    void operator()(T v) 
    { 
    // Use the v 
    } 
}; 

template <typename Handler, typename Container> 
struct handle_nested 
{ 
    void operator()(Container const& internal) 
    { 
    // inner loop, container type has been abstracted away and the handler type 
    for_each(internal.begin(), internal.end(), Handler()); 
    } 
}; 

// outer loop 
for_each(foo.begin(), foo.end(), handle_nested<do_foo<int>, std::vector<int> >()); 
1

Я думаю, что вложенные петли, как вы показали нам, не так уж плохи. Я бы рекомендовал выбрать лучшие имена для переменных управления. Если нет более лучших имен, возможно, outerIndex и innerIndex можно использовать ?! Кроме того, иногда перемещение тела (сложного) цикла в функцию улучшает читаемость.

0

Нет встроенной поддержки векторного цикла, но если все сделано правильно, интеллектуальный компилятор может оптимизировать ваши циклы для кода, что может использовать расширенные функции ЦП, что может повысить производительность.

Вообще говоря, нет ничего плохого в вложенных циклах. Но чаще всего, когда у вас есть вложенный цикл, этот код может быть оптимизирован для быстрого запуска. Но это сильно зависит от кода внутри цикла, т. Е. От того, что вы пытаетесь сделать с данными в векторах.

Как указывалось другими, использование итераторов улучшит ваш код с точки зрения соответствия лучшим практикам C++. Это не улучшит производительность, но это улучшит безопасность типов, и компилятор сможет указать вам на ошибки, которые ни вы, ни компилятор, возможно, не заметили иначе.

Если вещь, которую вы делаете внутри циклов, очень проста - скажем, увеличивая значение, если оно удовлетворяет условию, тогда стандартные алгоритмы C++, такие как std::for_each, и предикаты могут использоваться, чтобы сделать код более кратким и удобочитаемый.

Но не увлекайтесь этими вещами, держите их простыми. ;)

Смежные вопросы