Search
View source code
Display the source code in std/algorithm/iteration.d from which this page was generated on github.
Report a bug
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone.

# Template `std.algorithm.iteration.reduce`

Implements the homonym function (also known as `accumulate`, `compress`, `inject`, or `foldl`) present in various programming languages of functional flavor. There is also `fold` which does the same thing but with the opposite parameter order. The call `reduce!(fun)(seed, range)` first assigns `seed` to an internal variable `result`, also called the accumulator. Then, for each element `x` in `range`, `result = fun(result, x)` gets evaluated. Finally, `result` is returned. The one-argument version `reduce!(fun)(range)` works similarly, but it uses the first element of the range as the seed (the range must be non-empty).

``` template reduce(fun...) ; ```

## Contained Functions

NameDescription
reduce No-seed version. The first element of `r` is used as the seed's value.
reduce Seed version. The seed should be a single value if `fun` is a single function. If `fun` is multiple functions, then `seed` should be a `Tuple`, with one field per function in `f`.

## Returns

the accumulated `result`

## Parameters

NameDescription
fun one or more functions

`fold` is functionally equivalent to `reduce` with the argument order reversed, and without the need to use `tuple` for multiple seeds. This makes it easier to use in UFCS chains.

`sum` is similar to `reduce!((a, b) => a + b)` that offers pairwise summing of floating point numbers.

## Example

Many aggregate range operations turn out to be solved with `reduce` quickly and easily. The example below illustrates `reduce`'s remarkable power and flexibility.

``````import std.algorithm.comparison : max, min;
import std.math.operations : isClose;
import std.range;

int[] arr = [ 1, 2, 3, 4, 5 ];
// Sum all elements
auto sum = reduce!((a,b) => a + b)(0, arr);
writeln(sum); // 15

// Sum again, using a string predicate with "a" and "b"
sum = reduce!"a + b"(0, arr);
writeln(sum); // 15

// Compute the maximum of all elements
auto largest = reduce!(max)(arr);
writeln(largest); // 5

// Max again, but with Uniform Function Call Syntax (UFCS)
largest = arr.reduce!(max);
writeln(largest); // 5

// Compute the number of odd elements
auto odds = reduce!((a,b) => a + (b & 1))(0, arr);
writeln(odds); // 3

// Compute the sum of squares
auto ssquares = reduce!((a,b) => a + b * b)(0, arr);
writeln(ssquares); // 55

// Chain multiple ranges into seed
int[] a = [ 3, 4 ];
int[] b = [ 100 ];
auto r = reduce!("a + b")(chain(a, b));
writeln(r); // 107

// Mixing convertible types is fair game, too
double[] c = [ 2.5, 3.0 ];
auto r1 = reduce!("a + b")(chain(a, b, c));
assert(isClose(r1, 112.5));

// To minimize nesting of parentheses, Uniform Function Call Syntax can be used
auto r2 = chain(a, b, c).reduce!("a + b");
assert(isClose(r2, 112.5));
``````

## Example

Sometimes it is very useful to compute multiple aggregates in one pass. One advantage is that the computation is faster because the looping overhead is shared. That's why `reduce` accepts multiple functions. If two or more functions are passed, `reduce` returns a `Tuple` object with one member per passed-in function. The number of seeds must be correspondingly increased.

``````import std.algorithm.comparison : max, min;
import std.math.operations : isClose;
import std.math.algebraic : sqrt;
import std.typecons : tuple, Tuple;

double[] a = [ 3.0, 4, 7, 11, 3, 2, 5 ];
// Compute minimum and maximum in one pass
auto r = reduce!(min, max)(a);
// The type of r is Tuple!(int, int)
assert(isClose(r, 2));  // minimum
assert(isClose(r, 11)); // maximum

// Compute sum and sum of squares in one pass
r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a);
assert(isClose(r, 35));  // sum
assert(isClose(r, 233)); // sum of squares
// Compute average and standard deviation from the above
auto avg = r / a.length;
writeln(avg); // 5
auto stdev = sqrt(r / a.length - avg * avg);
writeln(cast(int)stdev); // 2
``````