Back
if_then_else
Overview
The if_then_else function applies conditional transformations to each element in a Serie. For each element, it evaluates a condition and applies either a "true" transformation or a "false" transformation based on the result. This provides a powerful way to selectively transform elements without using multiple operations.
Function Signatures
// Full version with index parameter
template <typename T, typename R>
Serie<R> if_then_else(const Serie<T> &serie,
std::function<bool(const T&, size_t)> condition,
std::function<R(const T&, size_t)> true_transform,
std::function<R(const T&, size_t)> false_transform);
// Simplified version without index parameter
template <typename T, typename R>
Serie<R> if_then_else(const Serie<T> &serie,
std::function<bool(const T&)> condition,
std::function<R(const T&)> true_transform,
std::function<R(const T&)> false_transform);
// Bound version for pipeline operations with index
template <typename T, typename R>
auto bind_if_then_else(std::function<bool(const T&, size_t)> condition,
std::function<R(const T&, size_t)> true_transform,
std::function<R(const T&, size_t)> false_transform);
// Simplified bound version without index parameter
template <typename T, typename R>
auto bind_if_then_else(std::function<bool(const T&)> condition,
std::function<R(const T&)> true_transform,
std::function<R(const T&)> false_transform);
Parameters
| Parameter | Type | Description |
|---|---|---|
| serie | const Serie<T>& | The input Serie to apply conditional transformations to. |
| condition | Function | Function that takes an element (and optionally its index) and returns a boolean value. This determines which transformation is applied to each element. |
| true_transform | Function | Function that takes an element (and optionally its index) and returns a transformed value. This is applied when the condition returns true. |
| false_transform | Function | Function that takes an element (and optionally its index) and returns a transformed value. This is applied when the condition returns false. |
Return Value
A new Serie where each element has been transformed according to the condition. The type of elements in the returned Serie corresponds to the return type of the transformation functions (type R), which may be different from the input Serie's element type.
Example Usage
Basic Conditional Transformations
// Create a Serie of numbers
df::Serie<int> numbers{-5, -2, 0, 3, 7, -1, 4};
// Replace negative values with zero, keep positive values
auto non_negative = df::if_then_else<int, int>(numbers,
[](int x) { return x < 0; }, // condition: is negative?
[](int) { return 0; }, // true transform: return 0
[](int x) { return x; }); // false transform: keep original value
// non_negative = {0, 0, 0, 3, 7, 0, 4}
// Take absolute values
auto absolute = df::if_then_else<int, int>(numbers,
[](int x) { return x < 0; }, // condition: is negative?
[](int x) { return -x; }, // true transform: negate
[](int x) { return x; }); // false transform: keep original value
// absolute = {5, 2, 0, 3, 7, 1, 4}
// Classify values as "positive", "negative", or "zero"
auto categories = df::if_then_else<int, std::string>(numbers,
[](int x) { return x == 0; }, // condition: is zero?
[](int) { return "zero"; }, // true transform: "zero"
[](int x) { return x > 0 ? "positive" : "negative"; }); // false transform: check sign
// categories = {"negative", "negative", "zero", "positive", "positive", "negative", "positive"}
Conditional Transformations with Index
// Create a Serie of numbers
df::Serie<int> numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// For even indices, square the value; for odd indices, double the value
auto transformed = df::if_then_else<int, int>(numbers,
[](int, size_t idx) { return idx % 2 == 0; }, // condition: even index?
[](int x, size_t) { return x * x; }, // true transform: square
[](int x, size_t) { return x * 2; }); // false transform: double
// transformed = {1, 4, 9, 8, 25, 12, 49, 16, 81, 20}
// Convert values to strings with position-dependent format
auto formatted = df::if_then_else<int, std::string>(numbers,
[](int, size_t idx) { return idx < 5; }, // condition: first half?
[](int x, size_t idx) { // true transform: format with index
return "Pos " + std::to_string(idx) + ": " + std::to_string(x);
},
[](int x, size_t) { // false transform: simple format
return "Val: " + std::to_string(x);
});
// formatted = {"Pos 0: 1", "Pos 1: 2", "Pos 2: 3", "Pos 3: 4", "Pos 4: 5",
// "Val: 6", "Val: 7", "Val: 8", "Val: 9", "Val: 10"}
Working with Complex Data Types
// Define a structure for a point
struct Point {
double x;
double y;
};
// Create a Serie of points
df::Serie<Point> points{
{1.0, 2.0}, {-3.0, 4.0}, {5.0, -6.0}, {-7.0, -8.0}, {9.0, 10.0}
};
// Reflect points that have a negative x-coordinate across the y-axis
auto reflected = df::if_then_else<Point, Point>(points,
[](const Point& p) { return p.x < 0; }, // condition: negative x?
[](const Point& p) { return Point{-p.x, p.y}; }, // true transform: reflect x
[](const Point& p) { return p; }); // false transform: keep original
// reflected = {{1.0, 2.0}, {3.0, 4.0}, {5.0, -6.0}, {7.0, -8.0}, {9.0, 10.0}}
// Compute distance from origin or norm depending on quadrant
auto metrics = df::if_then_else<Point, double>(points,
[](const Point& p) { return p.x >= 0 && p.y >= 0; }, // condition: first quadrant?
[](const Point& p) { // true transform: distance
return std::sqrt(p.x * p.x + p.y * p.y);
},
[](const Point& p) { // false transform: norm
return std::abs(p.x) + std::abs(p.y);
});
// metrics = {2.236..., 7.0, 11.0, 15.0, 13.453...}
Pipeline Examples
// Create a Serie of numbers
df::Serie<double> values{-5.5, 3.2, -1.7, 0.0, 4.8, -3.3, 2.1};
// Use bind_if_then_else in a pipeline
auto processed = values
| df::bind_map([](double x, size_t) { return x * 2; }) // Double all values
| df::bind_if_then_else<double, double>(
[](double x) { return x < 0; }, // condition: negative?
[](double x) { return x * x; }, // true transform: square
[](double x) { return x; } // false transform: keep as is
);
// processed = {121.0, 6.4, 11.56, 0.0, 9.6, 43.56, 4.2}
// Chain multiple if_then_else operations
auto multi_conditions = values
| df::bind_if_then_else<double, double>(
[](double x) { return x < 0; }, // condition: negative?
[](double x) { return -x; }, // true transform: absolute value
[](double x) { return x; } // false transform: keep as is
)
| df::bind_if_then_else<double, std::string>(
[](double x) { return x > 3.0; }, // condition: greater than 3?
[](double x) { return "High: " + std::to_string(x); }, // true transform
[](double x) { return "Low: " + std::to_string(x); } // false transform
);
// multi_conditions = {"High: 5.5", "High: 3.2", "Low: 1.7", "Low: 0", "High: 4.8", "High: 3.3", "Low: 2.1"}
Implementation Notes
- The if_then_else function creates a new Serie without modifying the original Serie.
- Both transformation functions are applied to every element; the condition determines which result is kept.
- The input and output types can be different, allowing for type conversions (e.g., numbers to strings).
- The condition and transformation functions can use the element index when needed.
- Multiple if_then_else operations can be chained in a pipeline to create complex conditional logic.
- Both transformation functions must return the same type (R), but this type can differ from the input Serie's type (T).