R/reduce.R
reduce.Rd
reduce()
is an operation that combines the elements of a vector
into a single value. The combination is driven by .f
, a binary
function that takes two values and returns a single value: reducing
f
over 1:3
computes the value f(f(1, 2), 3)
.
reduce(.x, .f, ..., .init, .dir = c("forward", "backward")) reduce2(.x, .y, .f, ..., .init)
.x  A list or atomic vector. 

.f  For For The reduction terminates early if 
...  Additional arguments passed on to the mapped function. 
.init  If supplied, will be used as the first value to start
the accumulation, rather than using 
.dir  The direction of reduction as a string, one of

.y  For 
When .f
is an associative operation like +
or c()
, the
direction of reduction does not matter. For instance, reducing the
vector 1:3
with the binary function +
computes the sum ((1 + 2) + 3)
from the left, and the same sum (1 + (2 + 3))
from the
right.
In other cases, the direction has important consequences on the
reduced value. For instance, reducing a vector with list()
from
the left produces a leftleaning nested list (or tree), while
reducing list()
from the right produces a rightleaning list.
reduce_right()
is softdeprecated as of purrr 0.3.0. Please use
the .dir
argument of reduce()
instead. Note that the algorithm
has changed. Whereas reduce_right()
computed f(f(3, 2), 1)
,
reduce(.dir = \"backward\")
computes f(1, f(2, 3))
. This is the
standard way of reducing from the right.
To update your code with the same reduction as reduce_right()
,
simply reverse your vector and use a left reduction:
# Before: reduce_right(1:3, f) # After: reduce(rev(1:3), f)
reduce2_right()
is softdeprecated as of purrr 0.3.0 without
replacement. It is not clear what algorithmic properties should a
right reduction have in this case. Please reach out if you know
about a use case for a right reduction with a ternary function.
accumulate()
for a version that returns all intermediate
values of the reduction.
# Reducing `+` computes the sum of a vector while reducing `*` # computes the product: 1:3 %>% reduce(`+`)#> [1] 61:10 %>% reduce(`*`)#> [1] 3628800# When the operation is associative, the direction of reduction # does not matter: reduce(1:4, `+`)#> [1] 10reduce(1:4, `+`, .dir = "backward")#> [1] 10# However with nonassociative operations, the reduced value will # be different as a function of the direction. For instance, # `list()` will create leftleaning lists when reducing from the # right, and rightleaning lists otherwise: str(reduce(1:4, list))#> List of 2 #> $ :List of 2 #> ..$ :List of 2 #> .. ..$ : int 1 #> .. ..$ : int 2 #> ..$ : int 3 #> $ : int 4#> List of 2 #> $ : int 1 #> $ :List of 2 #> ..$ : int 2 #> ..$ :List of 2 #> .. ..$ : int 3 #> .. ..$ : int 4# reduce2() takes a ternary function and a second vector that is # one element smaller than the first vector: paste2 < function(x, y, sep = ".") paste(x, y, sep = sep) letters[1:4] %>% reduce(paste2)#> [1] "a.b.c.d"#> [1] "ab.cd"#> [1] "0 2 6 4 8" "1 3 7 5 9"# You can shortcircuit a reduction and terminate it early by # returning a value wrapped in a done(). In the following example # we return early if the resultsofar, which is passed on the LHS, # meets a condition: paste3 < function(out, input, sep = ".") { if (nchar(out) > 4) { return(done(out)) } paste(out, input, sep = sep) } letters %>% reduce(paste3)#> [1] "a.b.c"# Here the early return branch checks the incoming inputs passed on # the RHS: paste4 < function(out, input, sep = ".") { if (input == "j") { return(done(out)) } paste(out, input, sep = sep) } letters %>% reduce(paste4)#> [1] "a.b.c.d.e.f.g.h.i"