Алгоритм STL / диапазонов для расчета средневзвешенного значения

Предположим, у меня есть вектор оценок, где оценка

struct Grade{
   const int grade;
   const int ECTS; // weight
};

Есть ли алгоритм / алгоритмы STL / range-v3, которые позволяют мне это сделать?

Я знаю, что мог бы сделать это с std:: accumulate с каким-нибудь причудливым типом в качестве аккумулятора (который запоминает сумму весов), но я ищу более простую альтернативу, если таковая существует.


person NoSenseEtAl    schedule 29.08.2019    source источник
comment
В настоящее время разрабатываются числовые алгоритмы с ограничениями: P1813 < / а>. Они включат что-то вроде: ranges::inner_product(grades, grades, 0, {}, {}, &Grade::grade, &Grade::ECTS);   -  person metalfox    schedule 30.08.2019


Ответы (2)


Сам тип Grade достаточно наворочен, чтобы действовать как тип аккумулятора.

auto [grade_sum, ects] = std::accumulate(
    grages.begin(), grades.end(), Grade {0,0}, 
    [] (Grade acc, Grade g) -> Grade {
        return { g.grade*g.ECTS + acc.grade,
                 g.ECTS         + acc.ECTS  };
});
// auto average_grade = grade_sum/ects;

Структурированная привязка C ++ 17 при необходимости может быть заменена на std::tie.

person Tom    schedule 03.09.2019
comment
Наверное auto average_grade = double(grade_sum) / ects. - person Jarod42; 03.09.2019
comment
Это действительно возможность. Кстати, спасибо за исправление порядка аккумулятора / значения;) - person Tom; 03.09.2019

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

auto average = ranges::inner_product(grades, grades, 0, {}, {}, &Grade::grade, &Grade::ECTS)
        / double(ranges::accumulate(grades, 0, {}, &Grade::ECTS));

Демо

person Jarod42    schedule 03.09.2019
comment
В настоящее время время компиляции ограничено. godbolt.org/z/I1_kGh против godbolt.org/z/eVvMJz или 14448 мс (диапазоны :: inner_product) против 3890 мс (std :: накопление) - person Porsche9II; 16.09.2019