STL алгоритмы и итераторы вместо циклов for - PullRequest
4 голосов
/ 23 февраля 2011

Полагаю, что должен быть какой-то код, написанный ниже, без использования циклов for и просто с использованием алгоритмов и итераторов STL.Если я не ошибаюсь, может кто-нибудь подсказать мне, как это сделать?

std::vector<double> A(N);
std::vector<double> B(N);
std::vector<double> C(N);
std::vector<double> D(N);

for(int i = 0; i < N; ++i)
  A[i] = myFunction1(i);

for(int i = 0; i < N; ++i)
  B[i] = myFunction2(A[i], i);

for(int i = 0; i < N; ++i)
  C[i] = myFunction3(A[i], B[i]);

for(int i = 0; i < N; ++i)
  D[i] = myFunction4(A[i], B[i], i);

Ответы [ 4 ]

4 голосов
/ 23 февраля 2011
typedef boost::counting_iterator<int> counter;

std::transform(counter(0), counter(N), A.begin(), myFunction1);
std::transform(A.begin(), A.end(), counter(0), B.begin(), myFunction2);
std::transform(A.begin(), A.end(), B.begin(), C.begin(), myFunction3);

Теперь напишите свою собственную версию std::transform, которая принимает троичную функцию:

template <typename In1, typename In2, typename In3, typename Out, typename FUNC>
Out transform3(In1 first1, In1 last1, In2 first2, In3 first3, Out out, FUNC f) {
    while (first1 != last1) {
        *out++ = f(*first1++, *first2++, *first3++);
    }
    return out;
}

transform3(A.begin(), A.end(), B.begin(), counter(0), D.begin(), myFunction4);

Полагаю, вы могли бы что-то сделать с шаблонами переменных в C ++ 0x, чтобы получить transform_N, но если это так, я не знаю, что это такое, я никогда не использовал их. Не уверен, что вы можете переслать переменное число аргументов с модификациями (в этом случае * ++ вокруг каждого как бы).

3 голосов
/ 23 февраля 2011

Вам понадобится немного BOOST , чтобы сделать все это с функциональной работой (или создать собственные версии boost :: counting_iterator)

//for(int i = 0; i < N; ++i)
//  A[i] = myFunction1(i);

std::transform(
     boost::counting_iterator<int>(0), 
     boost::counting_iterator<int>(N), 
     A.begin(), 
     &myFunction1);

//for(int i = 0; i < N; ++i)
//  B[i] = myFunction2(A[i], i);

std::transform(
     A.begin(),
     A.end(),
     boost::counting_iterator<int>(0), 
     B.begin(),
     &myFunction2);


//for(int i = 0; i < N; ++i)
//  C[i] = myFunction3(A[i], B[i]);
std::transform(
     A.begin(),
     A.end(),
     B.begin(),
     C.begin(),
     &myFunction3);

// The STL doesn't have a version of transform that takes three inputs, but given a transform_3 that does:
//for(int i = 0; i < N; ++i)
//  D[i] = myFunction4(A[i], B[i], i);
transform_3(
     A.begin(),
     A.end(),
     B.begin(),
     boost::counting_iterator<int>(0),
     D.begin(),
     &myFunction4);

Эта transform_3 функцияможет выглядеть примерно так:

// Untested code
template <class input1, class input2, class input3, class output, class oper>
output transform_3 (input1 in1begin, input1 in1end, input2 in2, input3 in3, output out, oper op)
{
    while (in1begin != in1end)
        *(out++) = op(*(in1begin++), *(in2++), *(in3++));
    return out;
}
1 голос
/ 23 февраля 2011

Почему бы не объединить 4 цикла в 1?

for(int i = 0; i < N; ++i) {
  A[i] = myFunction1(i);
  B[i] = myFunction2(A[i], i);
  C[i] = myFunction3(A[i], B[i]);
  D[i] = myFunction4(A[i], B[i], i);
}
0 голосов
/ 23 февраля 2011

Пример использования std::transform

#include <algorithm>
#include <vector>

double myFunction1(int) { return 0; }
double myFunction2(double, int) { return 1; }
double myFunction3(double, double) { return 2; }
double myFunction4(double, double, int) { return 3; }

struct int_sequence
{
    int_sequence(int i) : val(i) {}
    int_sequence operator++() { ++val; return *this; }
    int_sequence operator++(int) { return int_sequence(val++); }
    int operator*() const { return val; }
    bool operator!=(const int_sequence& other) const { return val != other.val; }
private:
    int val;
};

const size_t N = 100;

int main(void)
{
    std::vector<double> A(N);
    std::vector<double> B(N);
    std::vector<double> C(N);
    std::vector<double> D(N);

    //for(int i = 0; i < N; ++i)
    //    A[i] = myFunction1(i);
    std::transform(int_sequence(0), int_sequence(N), A.begin(), &myFunction1);

    //for(int i = 0; i < N; ++i)
    //  B[i] = myFunction2(A[i], i);
    std::transform(A.begin(), A.end(), int_sequence(0), B.begin(), &myFunction2);

    //for(int i = 0; i < N; ++i)
    //  C[i] = myFunction3(A[i], B[i]);
    std::transform(A.begin(), A.end(), B.begin(), C.begin(), &myFunction3);

    for(int i = 0; i < N; ++i)
      D[i] = myFunction4(A[i], B[i], i);
    // there is no std::transform for three-argument functions (yet)

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