Подведение итогов участников структуры в векторе

Чтобы узнать версию машинописного текста, установленную на моем компьютере, используйте эту команду в командной строке.

tsc - версия

14
задан 23 June 2009 в 04:22
поделиться

5 ответов

Суммирование STL может быть выполнено с помощью std :: accumulate

#include <functional>

accumulate(v.begin(), v.end(), 0, bind(plus<int>(), _1, bind(&ABCD::a, _2)))

. Если вы хотите, чтобы это было более универсальным, вы можете взять tr1 :: function для члена, который хотите привязать :

int sum_over_vec(const vector<ABCD>& v, const tr1::function<int (const ABCD&)>& member)
{
  return accumulate(v.begin(), v.end(),
                    0,
                    bind(plus<int>(),
                         _1,
                         bind(member, _2)));
};

// ...

int sum_a = sum_over_vec(vec, bind(&ABCD::a, _1));

Другой способ сделать это, вместо того, чтобы помещать вашу логику в функтор, - это поместить логику в итератор, используя итератор boost :: transform:

tr1::function<int (const ABCD&)> member(bind(&ABCD::a, _1));
accumulate(make_transform_iterator(v.begin(), member),
           make_transform_iterator(v.end(),   member),
           0);

EDITED TO ADD: синтаксис лямбда-выражения C ++ 11

Это становится несколько яснее с лямбдами C ++ 11 (хотя, к сожалению, не короче):

accumulate(v.begin(), v.end(), 0,
    [](int sum, const ABCD& curr) { return sum + curr.a });

и

int sum_over_vec(const vector<ABCD>& v, const std::function<int (const ABCD&)>& member)
{
  return accumulate(v.begin(), v.end(), 0,
      [&](int sum, const ABCD& curr) { return sum + member(curr}); });
};

Использование:

// Use a conversion from member function ptr to std::function.
int sum_a = sum_over_vec(vec, &ABCD::a);
// Or using a custom lambda sum the squares.
int sum_a_squared = sum_over_vec(vec,
    [](const ABCD& curr) { return curr.a * curr.a; });
16
ответ дан 1 December 2019 в 09:13
поделиться

Другой вариант - использовать указатель на члены:

int CalcSumOf(const VecABCD & vec, int ABCD::*member)
{
    int sum = 0;
    for(VecABCD::const_iterator it = vec.begin(), end = vec.end(); it != end; ++it)
        sum += (*it).*member;
    return sum;
}
...
int sumA = CalcSumOf(myVec, &ABCD::a);  // find sum of .a members
int sumB = CalcSumOf(myVec, &ABCD::b);  // find sum of .b members
// etc.
11
ответ дан 1 December 2019 в 09:13
поделиться

Используйте std :: accumulate :)

1
ответ дан 1 December 2019 в 09:13
поделиться

Вы можете использовать for_each . Это вариант.

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
typedef struct{
    int a;

}ABCD;

typedef vector<ABCD> vecABCD;

struct sum  : public unary_function<ABCD, void>
{
  sum(){count.a=count.b=count.c=count.d=0;}
  void operator() (ABCD x) {
       count.a+=x.a;
       count.b+=x.b;
       count.c+=x.c;
       count.d+=x.d;
   }
  ABCD count;
};

int main()
{

  ABCD s1={1,2,3,4};
  ABCD s2={5,6,7,8};

  vecABCD v;
  v.push_back(s1);
  v.push_back(s2);
  sum s = for_each(v.begin(), v.end(), sum());
  cout<<s.count.a<<endl;

}

вывод:

4
1
ответ дан 1 December 2019 в 09:13
поделиться

Добавим еще один вариант, к сожалению, некрасивый. Можно взять относительный адрес от начала структуры ABCD до ее члена с помощью функции offsetof. Доставьте возвращаемое значение функции, и она может производить подсчет с использованием относительного местоположения от начала каждой структуры. Если ваши типы могут отличаться от int, вы можете также предоставить информацию о размере.

0
ответ дан 1 December 2019 в 09:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: