Как облегчить вложенные циклы? - PullRequest
1 голос
/ 14 декабря 2010

Я часто зацикливаюсь на векторах векторов:

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]
 }
}

У меня нет хорошего минимального примера, почему «данные» лучше всего представлены вектором векторов int, но давайте не будем в этом сомневаться.

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

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

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

Заранее спасибо,

Кто

Ответы [ 5 ]

2 голосов
/ 14 декабря 2010

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

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

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 голос
/ 14 декабря 2010

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

1 голос
/ 14 декабря 2010

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

Свести 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 голос
/ 14 декабря 2010

Я думаю, что вы ищете шаблон итератора.

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

0 голосов
/ 14 декабря 2010

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...