Back
reduce
Overview
The reduce function aggregates all elements in a Serie into a single value by applying a reducer function against an accumulator. It's used for operations like summing, finding maximums, or building complex data structures from Serie elements.
Function Signatures
// Free function version
template <typename F, typename T, typename AccT>
auto reduce(F&& callback, const Serie<T>& serie, AccT initial);
// Member function version
template <typename F, typename AccT>
auto Serie<T>::reduce(F&& callback, AccT initial) const;
// Bound version for pipeline operations
template <typename F, typename AccT>
auto bind_reduce(F&& callback, AccT initial);
Parameters
| Parameter | Type | Description |
|---|---|---|
| callback | F&& (callable) | Reducer function that takes an accumulator, the current value, and optionally the index,
and returns
the updated accumulator. Should accept
(AccT accumulator, T value, size_t index).
|
| serie | const Serie<T>& | The Serie to reduce. |
| initial | AccT | Initial value for the accumulator. |
Return Value
The final accumulated value after processing all elements in the Serie. The type of the returned value matches the type of the initial accumulator.
Example Usage
Basic Reduction Examples
// Create a Serie of numbers
df::Serie<int> numbers{1, 2, 3, 4, 5};
// Sum all values using Serie member function
int sum = numbers.reduce([](int acc, int value, size_t) {
return acc + value;
}, 0); // 15
// Calculate product using free function
int product = df::reduce([](int acc, int value, size_t) {
return acc * value;
}, numbers, 1); // 120
// Find maximum value
int max = numbers.reduce([](int acc, int value, size_t) {
return (value > acc) ? value : acc;
}, std::numeric_limits<int>::min()); // 5
// Count elements matching a condition (even numbers)
int even_count = numbers.reduce([](int count, int value, size_t) {
return count + (value % 2 == 0 ? 1 : 0);
}, 0); // 2
Complex Reductions
// Create a Serie of values
df::Serie<double> values{1.5, 2.5, 3.5, 4.5, 5.5};
// Calculate average
double avg = values.reduce([](double acc, double value, size_t idx) {
return acc + value;
}, 0.0) / values.size(); // 3.5
// Calculate sum of squares
double sum_squares = values.reduce([](double acc, double value, size_t) {
return acc + (value * value);
}, 0.0); // 67.5
// Build a summary object
struct Summary {
double sum = 0;
double min = std::numeric_limits<double>::max();
double max = std::numeric_limits<double>::lowest();
size_t count = 0;
};
Summary stats = values.reduce([](Summary acc, double value, size_t) {
acc.sum += value;
acc.min = std::min(acc.min, value);
acc.max = std::max(acc.max, value);
acc.count++;
return acc;
}, Summary{});
// stats.sum == 17.5, stats.min == 1.5, stats.max == 5.5, stats.count == 5
// Calculate variance
double mean = stats.sum / stats.count;
double variance = values.reduce([mean](double acc, double value, size_t) {
double diff = value - mean;
return acc + (diff * diff);
}, 0.0) / stats.count; // 2.0
Building Collections
// Create a Serie of strings
df::Serie<std::string> words{"hello", "world", "dataframe", "library"};
// Concatenate all strings
std::string concatenated = words.reduce([](std::string acc, const std::string& value, size_t) {
return acc + value;
}, ""); // "helloworlddataframelibrary"
// Join with separator
std::string joined = words.reduce([](std::string acc, const std::string& value, size_t idx) {
return idx == 0 ? value : acc + ", " + value;
}, ""); // "hello, world, dataframe, library"
// Build a map of word lengths
std::map<std::string, size_t> word_lengths = words.reduce([](
std::map<std::string, size_t> acc,
const std::string& value,
size_t
) {
acc[value] = value.length();
return acc;
}, std::map<std::string, size_t>{});
// {"hello": 5, "world": 5, "dataframe": 9, "library": 7}
Pipeline Example
// Create a Serie of numbers
df::Serie<int> numbers{1, 2, 3, 4, 5};
// Use bind_reduce in a pipeline to calculate sum of squares
int sum_of_squares = numbers
| df::bind_map([](int x, size_t) { return x * x; }) // Square each number
| df::bind_reduce([](int acc, int value, size_t) { // Sum the squares
return acc + value;
}, 0);
// 1² + 2² + 3² + 4² + 5² = 55
// More complex pipeline
double result = df::Serie<double>{-2.5, 3.7, -1.2, 4.8, -0.9}
| df::bind_map([](double x, size_t) { return std::abs(x); }) // Take absolute values
| df::bind_map([](double x, size_t) { return x * x; }) // Square each value
| df::bind_reduce([](double acc, double value, size_t) { // Calculate average
return acc + value;
}, 0.0) / 5.0; // ~7.98
Implementation Notes
- The reduce function processes elements from left to right (first to last).
- The initial value is important for correctness and should be chosen carefully (e.g., 0 for sum, 1 for product, empty container for collection building).
- The type of the accumulator can be different from the type of the Serie elements.
- Unlike map and forEach, reduce produces a single value rather than a new Serie.
- The index parameter in the callback function is optional.