DMarlon Studio

Lección 12 · 12 de 20

Algoritmos de la STL · C++

Procese datos en C++ con transform, accumulate, count_if, find_if y remove_if con erase: las ventas de una tienda sin escribir bucles.

C++ · Algoritmos de la STL en DMarlon Studio: el código del ejemplo y su salida en la terminal

Las cabeceras <algorithm> y <numeric> traen decenas de algoritmos que trabajan sobre un rango, de begin() a end(). Con lambdas, sustituyen a muchos bucles y dejan claro de un vistazo qué hace cada línea.

`remove_if` no borra nada: mueve al final los elementos que cumplen la condición (aquí la devolución, con importe negativo) y devuelve dónde empiezan. `erase` recorta desde ahí hasta el final. Las dos juntas forman el modismo *erase-remove*; si se olvida la segunda, el vector conserva su tamaño.

`transform` calcula un valor nuevo por cada elemento y lo escribe en otro rango: withVat se crea con el tamaño justo y recibe cada precio con el 21 % de IVA. El ratón, tercero de la lista tras quitar la devolución, pasa de 19,50 a 23,595.

`accumulate` reduce todo a un valor, empezando por el tercer argumento. Escriba 0.0 y no 0: con un entero, la suma se haría con enteros y perdería los decimales. Con una lambda suma el campo amount de cada venta; sin ella, suma directamente los double de withVat.

`count_if` cuenta los elementos que cumplen una condición (dos ventas de 100 euros o más) y `find_if` devuelve un iterador al primero que la cumple, o end() si no hay ninguno; por eso se compara con sales.end() antes de usar cheap->product.

Código · main.cpp

#include <algorithm>#include <iostream>#include <numeric>#include <string>#include <vector>struct Sale { std::string product; double amount; };int main() {    std::vector<Sale> sales = {{"Keyboard", 45}, {"Monitor", 189}, {"Refund", -45},                               {"Mouse", 19.5}, {"Laptop", 899}, {"Cable", 7.5}};    // remove_if moves the unwanted items to the end; erase cuts them off.    auto isRefund = [](const Sale& s) { return s.amount < 0; };    sales.erase(std::remove_if(sales.begin(), sales.end(), isRefund), sales.end());    // transform: one new value per element (the price with 21% VAT).    std::vector<double> withVat(sales.size());    std::transform(sales.begin(), sales.end(), withVat.begin(), [](const Sale& s) { return s.amount * 1.21; });    // accumulate: folds every element into one value, starting from 0.0.    double net = std::accumulate(sales.begin(), sales.end(), 0.0,                                 [](double sum, const Sale& s) { return sum + s.amount; });    double gross = std::accumulate(withVat.begin(), withVat.end(), 0.0);    auto big = std::count_if(sales.begin(), sales.end(), [](const Sale& s) { return s.amount >= 100; });    auto cheap = std::find_if(sales.begin(), sales.end(), [](const Sale& s) { return s.amount < 10; });    std::cout << "Sales kept: " << sales.size() << " (first: " << sales.front().product << ")\n";    std::cout << "Mouse with VAT: " << withVat[2] << " EUR\n";    std::cout << "Net: " << net << " EUR, with VAT: " << gross << " EUR\n";    std::cout << "Sales of 100 EUR or more: " << big << "\n";    if (cheap != sales.end()) std::cout << "First under 10 EUR: " << cheap->product << "\n";}

Salida · c++ -std=c++17 main.cpp -o main && ./main

Sales kept: 5 (first: Keyboard)
Mouse with VAT: 23.595 EUR
Net: 1160 EUR, with VAT: 1403.6 EUR
Sales of 100 EUR or more: 2
First under 10 EUR: Cable

Para recordar

  • Los algoritmos reciben un rango: v.begin(), v.end().
  • remove_if + erase borran de verdad los elementos que cumplen una condición.
  • transform calcula un valor nuevo por elemento.
  • accumulate(b, e, 0.0) suma; el tipo del valor inicial manda.
  • find_if devuelve end() si no encuentra nada: compruébelo antes de usarlo.

Ejercicio

Use std::max_element con una lambda para encontrar la venta más alta y escriba su producto y su importe. Después, cuente con count_if las ventas de menos de 50 euros.