std::transform_reduce în C++

Transformă fiecare element și combină rezultatele într-o singură valoare, într-o singură trecere.

Sintaxă
T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init);
T transform_reduce(InputIt first, InputIt last, T init, BinaryOp reduce, UnaryOp transform);

Ce face std::transform_reduce

std::transform_reduce unește std::transform și std::reduce: aplică o funcție fiecărui element și adună (sau combină) rezultatele, fără vector intermediar.

Varianta cu două intervale și fără funcții calculează produsul scalar, ca std::inner_product. Ca la reduce, ordinea combinării nu este fixă, deci operația de reducere trebuie să fie asociativă și comutativă.

Parametri

Parametru Descriere
first, last Intervalul (sau primul interval).
first2 Pentru varianta cu două intervale: începutul celui de-al doilea.
init Valoarea de pornire.
reduce Operația de combinare (de exemplu std::plus<>()).
transform Funcția aplicată fiecărui element.

Ce returnează

Rezultatul combinat.

Exemple

Exemplul 1: Valoarea totală a stocului

#include <functional>
#include <numeric>
#include <print>
#include <string>
#include <vector>

struct Produs {
    std::string nume;
    int bucati;
    double pret;
};

int main() {
    std::vector<Produs> stoc{{"Pix", 120, 3.5}, {"Caiet", 80, 7.0}, {"Rucsac", 6, 149.9}};

    double valoare = std::transform_reduce(stoc.begin(), stoc.end(), 0.0, std::plus<>(),
                                           [](const Produs& p) { return p.bucati * p.pret; });
    std::println("Valoarea stocului: {:.2f} lei", valoare);
}

Rezultat

Valoarea stocului: 1879.40 lei

Exemplul 2: Produs scalar și lungimea totală a textelor

#include <functional>
#include <numeric>
#include <print>
#include <string>
#include <vector>

int main() {
    std::vector<int> a{1, 2, 3};
    std::vector<int> b{4, 5, 6};
    std::println("Produs scalar: {}", std::transform_reduce(a.begin(), a.end(), b.begin(), 0));

    std::vector<std::string> mesaje{"Salut", "Ce faci?", "Ne vedem"};
    auto caractere = std::transform_reduce(mesaje.begin(), mesaje.end(), std::size_t{0}, std::plus<>(),
                                           [](const std::string& m) { return m.size(); });
    std::println("Caractere: {}", caractere);
}

Rezultat

Produs scalar: 32
Caractere: 21

Greșeli frecvente

  • Inversezi ordinea funcțiilor: în varianta cu un interval, întâi vine operația de reducere, apoi transformarea.

Comenzi înrudite

  • std::reduce: Ca accumulate, dar fără ordine fixă a operațiilor, ceea ce permite calcul în paralel.
  • std::inner_product: Calculează produsul scalar: suma produselor elementelor aflate pe aceleași poziții în două intervale.
  • std::transform: Aplică o funcție fiecărui element și scrie rezultatele în alt interval (sau în același).
  • std::accumulate: Adună toate elementele unui interval pornind de la o valoare inițială (sau le combină cu o operație dată).