Skip to content

Commit b739916

Browse files
committed
Implement vararg methods for mapreduce similar to map, fixes #27704.
1 parent d60503a commit b739916

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Standard library changes
4949
* A no-argument construct to `Ptr{T}` has been added which constructs a null pointer ([#30919])
5050
* `strip` now accepts a function argument in the same manner as `lstrip` and `rstrip` ([#31211])
5151
* `mktempdir` now accepts a `prefix` keyword argument to customize the file name ([#31230], [#22922])
52+
* `mapreduce` now accept multiple iterators, similar to `map` ([#?????]).
5253

5354
#### LinearAlgebra
5455

base/reduce.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,9 @@ mapreduce_impl(f, op, A::AbstractArray, ifirst::Integer, ilast::Integer) =
179179
mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op))
180180

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

207211
# Note: sum_seq usually uses four or more accumulators after partial
208212
# unrolling, so each accumulator gets at most 256 numbers

base/reducedim.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,14 @@ reducedim!(op, R::AbstractArray{RT}, A::AbstractArray) where {RT} =
278278
mapreducedim!(identity, op, R, A)
279279

280280
"""
281-
mapreduce(f, op, A::AbstractArray; dims=:, [init])
281+
mapreduce(f, op, A::AbstractArray...; dims=:, [init])
282282
283283
Evaluates to the same as `reduce(op, map(f, A); dims=dims, init=init)`, but is generally
284284
faster because the intermediate array is avoided.
285285
286+
!!! compat "Julia 1.2"
287+
`mapreduce` with multiple iterators requires Julia 1.2 or later.
288+
286289
# Examples
287290
```jldoctest
288291
julia> a = reshape(Vector(1:16), (4,4))
@@ -302,6 +305,7 @@ julia> mapreduce(isodd, |, a, dims=1)
302305
```
303306
"""
304307
mapreduce(f, op, A::AbstractArray; dims=:, kw...) = _mapreduce_dim(f, op, kw.data, A, dims)
308+
mapreduce(f, op, A::AbstractArray...; kw...) = reduce(op, map(f, A...); kw...)
305309

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

test/reduce.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,27 @@ using .Main.OffsetArrays
4343
@test mapreduce(-, +, [-10 -9 -3]) == ((10 + 9) + 3)
4444
@test mapreduce((x)->x[1:3], (x,y)->"($x+$y)", ["abcd", "efgh", "01234"]) == "((abc+efg)+012)"
4545

46+
# mapreduce with multiple iterators
47+
@test mapreduce(*, +, (i for i in 2:3), (i for i in 4:5)) == 23
48+
@test mapreduce(*, +, (i for i in 2:3), (i for i in 4:5); init = 2) == 25
49+
@test mapreduce(*, (x,y)->"($x+$y)", ["a", "b", "c"], ["d", "e", "f"]) == "((ad+be)+cf)"
50+
@test mapreduce(*, (x,y)->"($x+$y)", ["a", "b", "c"], ["d", "e", "f"]; init = "gh") ==
51+
"(((gh+ad)+be)+cf)"
52+
53+
@test mapreduce(*, +, [2, 3], [4, 5]) == 23
54+
@test mapreduce(*, +, [2, 3], [4, 5]; init = 2) == 25
55+
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 1) == [23]
56+
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 1, init = 2) == [25]
57+
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 2) == [8, 15]
58+
@test mapreduce(*, +, [2, 3], [4, 5]; dims = 2, init = 2) == [10, 17]
59+
60+
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]) == 110
61+
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; init = 2) == 112
62+
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 1) == [44 66]
63+
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 1, init = 2) == [46 68]
64+
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 2) == reshape([33, 77], :, 1)
65+
@test mapreduce(*, +, [2 3; 4 5], [6 7; 8 9]; dims = 2, init = 2) == reshape([35, 79], :, 1)
66+
4667
# mapreduce() for 1- 2- and n-sized blocks (PR #19325)
4768
@test mapreduce(-, +, [-10]) == 10
4869
@test mapreduce(abs2, +, [-9, -3]) == 81 + 9

0 commit comments

Comments
 (0)