Skip to content

Commit

Permalink
Merge pull request #31532 from JuliaLang/fe/multi-arg-mapreduce
Browse files Browse the repository at this point in the history
Implement vararg methods for mapreduce similar to map, fixes #27704.
  • Loading branch information
mbauman committed Apr 3, 2019
2 parents b3b6d03 + 48fd53d commit a24c38c
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 4 deletions.
15 changes: 14 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Standard library changes
* `nextfloat(::BigFloat)` and `prevfloat(::BigFloat)` now returns a value with the same precision
as their argument, which means that (in particular) `nextfloat(prevfloat(x)) == x` whereas
previously this could result in a completely different value with a different precision ([#31310])
* `mapreduce` now accept multiple iterators, similar to `map` ([#31532]).

#### LinearAlgebra

Expand Down Expand Up @@ -108,6 +109,7 @@ Deprecated or removed

<!--- generated by NEWS-update.jl: -->
[#21598]: https://github.com/JuliaLang/julia/issues/21598
[#22922]: https://github.com/JuliaLang/julia/issues/22922
[#24980]: https://github.com/JuliaLang/julia/issues/24980
[#28850]: https://github.com/JuliaLang/julia/issues/28850
[#29777]: https://github.com/JuliaLang/julia/issues/29777
Expand All @@ -117,16 +119,27 @@ Deprecated or removed
[#30200]: https://github.com/JuliaLang/julia/issues/30200
[#30298]: https://github.com/JuliaLang/julia/issues/30298
[#30323]: https://github.com/JuliaLang/julia/issues/30323
[#30349]: https://github.com/JuliaLang/julia/issues/30349
[#30372]: https://github.com/JuliaLang/julia/issues/30372
[#30382]: https://github.com/JuliaLang/julia/issues/30382
[#30577]: https://github.com/JuliaLang/julia/issues/30577
[#30583]: https://github.com/JuliaLang/julia/issues/30583
[#30584]: https://github.com/JuliaLang/julia/issues/30584
[#30593]: https://github.com/JuliaLang/julia/issues/30593
[#30604]: https://github.com/JuliaLang/julia/issues/30604
[#30618]: https://github.com/JuliaLang/julia/issues/30618
[#30670]: https://github.com/JuliaLang/julia/issues/30670
[#30712]: https://github.com/JuliaLang/julia/issues/30712
[#30724]: https://github.com/JuliaLang/julia/issues/30724
[#30915]: https://github.com/JuliaLang/julia/issues/30915
[#30919]: https://github.com/JuliaLang/julia/issues/30919
[#30938]: https://github.com/JuliaLang/julia/issues/30938
[#31008]: https://github.com/JuliaLang/julia/issues/31008
[#31009]: https://github.com/JuliaLang/julia/issues/31009
[#31125]: https://github.com/JuliaLang/julia/issues/31125
[#31211]: https://github.com/JuliaLang/julia/issues/31211
[#31230]: https://github.com/JuliaLang/julia/issues/31230
[#31235]: https://github.com/JuliaLang/julia/issues/31235
[#31310]: https://github.com/JuliaLang/julia/issues/31310
[#31441]: https://github.com/JuliaLang/julia/issues/31441
[#31451]: https://github.com/JuliaLang/julia/issues/31451
[#31532]: https://github.com/JuliaLang/julia/issues/31532
8 changes: 6 additions & 2 deletions base/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ mapreduce_impl(f, op, A::AbstractArray, ifirst::Integer, ilast::Integer) =
mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op))

"""
mapreduce(f, op, itr; [init])
mapreduce(f, op, itrs...; [init])
Apply function `f` to each element in `itr`, and then reduce the result using the binary
Apply function `f` to each element(s) in `itrs`, and then reduce the result using the binary
function `op`. If provided, `init` must be a neutral element for `op` that will be returned
for empty collections. It is unspecified whether `init` is used for non-empty collections.
In general, it will be necessary to provide `init` to work with empty collections.
Expand All @@ -191,6 +191,9 @@ In general, it will be necessary to provide `init` to work with empty collection
intermediate collection needs to be created. See documentation for [`reduce`](@ref) and
[`map`](@ref).
!!! compat "Julia 1.2"
`mapreduce` with multiple iterators requires Julia 1.2 or later.
# Examples
```jldoctest
julia> mapreduce(x->x^2, +, [1:3;]) # == 1 + 4 + 9
Expand All @@ -203,6 +206,7 @@ implementations may reuse the return value of `f` for elements that appear multi
guaranteed left or right associativity and invocation of `f` for every value.
"""
mapreduce(f, op, itr; kw...) = mapfoldl(f, op, itr; kw...)
mapreduce(f, op, itrs...; kw...) = reduce(op, Generator(f, itrs...); kw...)

# Note: sum_seq usually uses four or more accumulators after partial
# unrolling, so each accumulator gets at most 256 numbers
Expand Down
6 changes: 5 additions & 1 deletion base/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,14 @@ reducedim!(op, R::AbstractArray{RT}, A::AbstractArray) where {RT} =
mapreducedim!(identity, op, R, A)

"""
mapreduce(f, op, A::AbstractArray; dims=:, [init])
mapreduce(f, op, A::AbstractArray...; dims=:, [init])
Evaluates to the same as `reduce(op, map(f, A); dims=dims, init=init)`, but is generally
faster because the intermediate array is avoided.
!!! compat "Julia 1.2"
`mapreduce` with multiple iterators requires Julia 1.2 or later.
# Examples
```jldoctest
julia> a = reshape(Vector(1:16), (4,4))
Expand All @@ -302,6 +305,7 @@ julia> mapreduce(isodd, |, a, dims=1)
```
"""
mapreduce(f, op, A::AbstractArray; dims=:, kw...) = _mapreduce_dim(f, op, kw.data, A, dims)
mapreduce(f, op, A::AbstractArray...; kw...) = reduce(op, map(f, A...); kw...)

_mapreduce_dim(f, op, nt::NamedTuple{(:init,)}, A::AbstractArray, ::Colon) = mapfoldl(f, op, A; nt...)

Expand Down
21 changes: 21 additions & 0 deletions test/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ using .Main.OffsetArrays
@test mapreduce(-, +, [-10 -9 -3]) == ((10 + 9) + 3)
@test mapreduce((x)->x[1:3], (x,y)->"($x+$y)", ["abcd", "efgh", "01234"]) == "((abc+efg)+012)"

# mapreduce with multiple iterators
@test mapreduce(*, +, (i for i in 2:3), (i for i in 4:5)) == 23
@test mapreduce(*, +, (i for i in 2:3), (i for i in 4:5); init = 2) == 25
@test mapreduce(*, (x,y)->"($x+$y)", ["a", "b", "c"], ["d", "e", "f"]) == "((ad+be)+cf)"
@test mapreduce(*, (x,y)->"($x+$y)", ["a", "b", "c"], ["d", "e", "f"]; init = "gh") ==
"(((gh+ad)+be)+cf)"

@test mapreduce(*, +, [2, 3], [4, 5]) == 23
@test mapreduce(*, +, [2, 3], [4, 5]; init = 2) == 25
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 1) == [23]
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 1, init = 2) == [25]
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 2) == [8, 15]
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 2, init = 2) == [10, 17]

@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]) == 110
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; init = 2) == 112
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 1) == [44 66]
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 1, init = 2) == [46 68]
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 2) == reshape([33, 77], :, 1)
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 2, init = 2) == reshape([35, 79], :, 1)

# mapreduce() for 1- 2- and n-sized blocks (PR #19325)
@test mapreduce(-, +, [-10]) == 10
@test mapreduce(abs2, +, [-9, -3]) == 81 + 9
Expand Down

0 comments on commit a24c38c

Please sign in to comment.