Giao diện
🔄 Transform & Reduce — Functional Operations
transform và accumulate là workhorses của functional-style C++ — biến đổi và aggregate data một cách elegant. std::transform — Map Operation
Single Range Transform
cpp
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
std::vector<int> result(v.size());
// Transform mỗi element
std::transform(v.begin(), v.end(), result.begin(),
[](int x) { return x * x; });
// result = [1, 4, 9, 16, 25]
// Transform in-place
std::transform(v.begin(), v.end(), v.begin(),
[](int x) { return x * 2; });
// v = [2, 4, 6, 8, 10]
return 0;
}Two Ranges Transform
cpp
std::vector<int> a = {1, 2, 3, 4, 5};
std::vector<int> b = {10, 20, 30, 40, 50};
std::vector<int> c(a.size());
// Combine two ranges
std::transform(a.begin(), a.end(), b.begin(), c.begin(),
[](int x, int y) { return x + y; });
// c = [11, 22, 33, 44, 55]
// Multiply pairwise
std::transform(a.begin(), a.end(), b.begin(), c.begin(),
std::multiplies<int>());
// c = [10, 40, 90, 160, 250]std::accumulate — Reduce/Fold
cpp
#include <numeric>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
// Sum (default operation = +)
int sum = std::accumulate(v.begin(), v.end(), 0);
// 0 + 1 + 2 + 3 + 4 + 5 = 15
// Product
int product = std::accumulate(v.begin(), v.end(), 1,
std::multiplies<int>());
// 1 * 1 * 2 * 3 * 4 * 5 = 120
// Custom accumulation
int sumOfSquares = std::accumulate(v.begin(), v.end(), 0,
[](int acc, int x) { return acc + x * x; });
// 0 + 1 + 4 + 9 + 16 + 25 = 55
return 0;
}String Concatenation
cpp
std::vector<std::string> words = {"Hello", " ", "World", "!"};
std::string sentence = std::accumulate(
words.begin(), words.end(),
std::string(), // Initial value (empty string)
[](const std::string& acc, const std::string& s) {
return acc + s;
});
// "Hello World!"
// Hoặc đơn giản hơn:
std::string s2 = std::accumulate(words.begin(), words.end(), std::string());std::reduce (C++17) — Parallel-friendly
cpp
#include <numeric>
#include <execution> // C++17 parallel
std::vector<int> v = {1, 2, 3, 4, 5};
// Sequential reduce
int sum = std::reduce(v.begin(), v.end());
// Parallel reduce (C++17)
int psum = std::reduce(std::execution::par, v.begin(), v.end());
// Với initial value và binary op
int product = std::reduce(v.begin(), v.end(), 1, std::multiplies<int>());📌 reduce vs accumulate
accumulate: Sequential, left-to-right, guaranteed orderreduce: May reorder operations, parallelizable- Dùng
reducekhi operation là commutative và associative
std::inner_product — Dot Product
cpp
#include <numeric>
std::vector<int> a = {1, 2, 3};
std::vector<int> b = {4, 5, 6};
// Dot product: 1*4 + 2*5 + 3*6 = 32
int dot = std::inner_product(a.begin(), a.end(), b.begin(), 0);
// Generalized: init + sum(a[i] * b[i])
int result = std::inner_product(a.begin(), a.end(), b.begin(), 0,
std::plus<>(), // Reduce operation
std::multiplies<>() // Combine operation
);std::partial_sum — Prefix Sums
cpp
#include <numeric>
std::vector<int> v = {1, 2, 3, 4, 5};
std::vector<int> prefix(v.size());
std::partial_sum(v.begin(), v.end(), prefix.begin());
// prefix = [1, 3, 6, 10, 15]
// 1, 1+2=3, 1+2+3=6, ...
// In-place
std::partial_sum(v.begin(), v.end(), v.begin());std::adjacent_difference
cpp
std::vector<int> v = {1, 3, 6, 10, 15};
std::vector<int> diff(v.size());
std::adjacent_difference(v.begin(), v.end(), diff.begin());
// diff = [1, 2, 3, 4, 5]
// First stays same, rest = current - previousstd::iota — Generate Sequential Values
cpp
#include <numeric>
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1);
// v = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
std::iota(v.begin(), v.end(), 100);
// v = [100, 101, 102, ..., 109]std::for_each
cpp
std::vector<int> v = {1, 2, 3, 4, 5};
// Side effects (print)
std::for_each(v.begin(), v.end(), [](int x) {
std::cout << x << " ";
});
// Modification
std::for_each(v.begin(), v.end(), [](int& x) {
x *= 2;
});
// v = [2, 4, 6, 8, 10]Chaining Operations
cpp
#include <algorithm>
#include <numeric>
#include <vector>
int main() {
std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Pipeline: filter evens → square → sum
std::vector<int> evens;
std::copy_if(data.begin(), data.end(), std::back_inserter(evens),
[](int x) { return x % 2 == 0; });
// evens = [2, 4, 6, 8, 10]
std::transform(evens.begin(), evens.end(), evens.begin(),
[](int x) { return x * x; });
// evens = [4, 16, 36, 64, 100]
int sum = std::accumulate(evens.begin(), evens.end(), 0);
// 220
return 0;
}One-liner với Ranges (C++20)
cpp
// C++20 Ranges — elegant pipeline
#include <ranges>
auto result = data
| std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * x; });
int sum = std::accumulate(result.begin(), result.end(), 0);Practical Examples
Calculate Statistics
cpp
std::vector<double> grades = {85, 90, 78, 92, 88, 95, 73, 89};
double sum = std::accumulate(grades.begin(), grades.end(), 0.0);
double avg = sum / grades.size();
auto [minIt, maxIt] = std::minmax_element(grades.begin(), grades.end());
double min = *minIt;
double max = *maxIt;
std::cout << "Average: " << avg << std::endl; // 86.25
std::cout << "Min: " << min << ", Max: " << max << std::endl; // 73, 95Word Lengths
cpp
std::vector<std::string> words = {"hello", "world", "cpp", "programming"};
std::vector<size_t> lengths(words.size());
std::transform(words.begin(), words.end(), lengths.begin(),
[](const std::string& s) { return s.length(); });
// lengths = [5, 5, 3, 11]
size_t totalChars = std::accumulate(lengths.begin(), lengths.end(), 0ULL);
// 24📚 Tổng kết
| Algorithm | Purpose | Example |
|---|---|---|
transform | Apply function to each | Square all |
accumulate | Reduce to single value | Sum |
reduce (C++17) | Parallel-friendly accumulate | |
inner_product | Dot product | a·b |
partial_sum | Prefix sums | Running total |
iota | Generate sequence | 1, 2, 3, ... |
for_each | Apply side effects | Print all |
➡️ Tiếp theo
Tiếp theo: Code Golf — STL power demonstrations.