Суммирование всех похожих полей в массиве struct - PullRequest
0 голосов
/ 13 сентября 2018

Предположим, что существует структурный массив

struct Monthly {

        int totalLanded;
        int totalDeparted;
        int greatestLanded;
        int leastDeparted;

    };

    const int MONTHS = 12;
    Monthly travel[MONTHS];

Существует ли метод суммирования всех значений totalLanded из всех членов массива одним оператором без использования цикла?

Чтобы это выглядело примерно так («псевдокод»):

int sum = summate(travel[].totalLanded)

Что бы присвоить сумме все значения totalLanded из всего массива структуры.

Спасибо

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

Вы можете использовать std::accumulate для генерации вашей суммы. Первые два аргумента указывают диапазон, по которому вычисляется сумма. Третий аргумент указывает начальное значение и тип результата. Последний аргумент требует замыкания или функции, которая определяет, как каждый элемент вносит вклад в сумму.

#include <iterator> // For std::begin, std::end
#include <numeric>  // For std::accumulate

int main()
{
    const auto result = std::accumulate(
        std::begin(travel), // Iterate from here
        std::end(travel),   //  to here
        0,                  // Count starting at zero, return an int
        [](const auto sum, const auto & next) { // How to count each element
            return sum + next.totalLanded;
        });
}

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

#include <iterator>
#include <numeric>

template<class T, class M>
auto sum_members(const T & container, M member)
{
    // Deduce the type of the member
    // It's important to specify what type to use in the sum
    using t_element = decltype(*std::begin(container));
    using t_value = decltype(std::declval<t_element>().*member);

    return std::accumulate(
        std::begin(container),
        std::end(container),
        t_value{},
        [member](const auto sum, const auto & next) {
            return sum + (next.*member);
        });
}


int main()
{
    const auto total_landed = sum_members(travel, &Monthly::totalLanded);
    const auto total_departed = sum_members(travel, &Monthly::totalDeparted);
    // etc.
}
0 голосов
/ 14 сентября 2018

С range-v3 : это может быть:

int sum = ranges::accumulate(travel, 0, std::plus<>{}, &Monthly::totalLanded);

Демо

0 голосов
/ 14 сентября 2018

Стандартной библиотечной функцией для этого является std::accumulate.Вы бы использовали его как

auto total = std::accumulate(std::begin(travel), 
                             std::end(travel), 
                             0, 
                             [](auto accum, const auto& m) { return accum + m.totalLanded; });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...