-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement accumulate
and friends for arbitrary iterators
#34656
Changes from all commits
0098f07
78f3885
78a6c44
7a4d7fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -443,40 +443,51 @@ reverse(f::Filter) = Filter(f.flt, reverse(f.itr)) | |||||||||||||
|
||||||||||||||
# Accumulate -- partial reductions of a function over an iterator | ||||||||||||||
|
||||||||||||||
struct Accumulate{F,I} | ||||||||||||||
struct Accumulate{F,I,T} | ||||||||||||||
f::F | ||||||||||||||
itr::I | ||||||||||||||
init::T | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
""" | ||||||||||||||
Iterators.accumulate(f, itr) | ||||||||||||||
Iterators.accumulate(f, itr; [init]) | ||||||||||||||
|
||||||||||||||
Given a 2-argument function `f` and an iterator `itr`, return a new | ||||||||||||||
iterator that successively applies `f` to the previous value and the | ||||||||||||||
next element of `itr`. | ||||||||||||||
|
||||||||||||||
This is effectively a lazy version of [`Base.accumulate`](@ref). | ||||||||||||||
|
||||||||||||||
!!! compat "Julia 1.5" | ||||||||||||||
Keyword argument `init` is added in Julia 1.5. | ||||||||||||||
|
||||||||||||||
# Examples | ||||||||||||||
```jldoctest | ||||||||||||||
julia> f = Iterators.accumulate(+, [1,2,3,4]) | ||||||||||||||
Base.Iterators.Accumulate{typeof(+),Array{Int64,1}}(+, [1, 2, 3, 4]) | ||||||||||||||
julia> f = Iterators.accumulate(+, [1,2,3,4]); | ||||||||||||||
|
||||||||||||||
julia> foreach(println, f) | ||||||||||||||
1 | ||||||||||||||
3 | ||||||||||||||
6 | ||||||||||||||
10 | ||||||||||||||
|
||||||||||||||
julia> f = Iterators.accumulate(+, [1,2,3]; init = 100); | ||||||||||||||
|
||||||||||||||
julia> foreach(println, f) | ||||||||||||||
101 | ||||||||||||||
103 | ||||||||||||||
106 | ||||||||||||||
``` | ||||||||||||||
""" | ||||||||||||||
accumulate(f, itr) = Accumulate(f, itr) | ||||||||||||||
accumulate(f, itr; init = Base._InitialValue()) = Accumulate(f, itr, init) | ||||||||||||||
|
||||||||||||||
function iterate(itr::Accumulate) | ||||||||||||||
state = iterate(itr.itr) | ||||||||||||||
if state === nothing | ||||||||||||||
return nothing | ||||||||||||||
end | ||||||||||||||
return (state[1], state) | ||||||||||||||
val = Base.BottomRF(itr.f)(itr.init, state[1]) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since Before: julia> collect(Iterators.accumulate(+, (x for x in [true])))
1-element Array{Bool,1}:
1
julia> collect(Iterators.accumulate(+, (x for x in [true, true, false])))
3-element Array{Integer,1}:
true
2
2 After: julia> collect(Iterators.accumulate(+, (x for x in [true])))
1-element Array{Int64,1}:
1
julia> collect(Iterators.accumulate(+, (x for x in [true, true, false])))
3-element Array{Int64,1}:
1
2
2 Ref: Lines 73 to 78 in 3720edf
|
||||||||||||||
return (val, (val, state[2])) | ||||||||||||||
end | ||||||||||||||
|
||||||||||||||
function iterate(itr::Accumulate, state) | ||||||||||||||
|
@@ -491,7 +502,7 @@ end | |||||||||||||
length(itr::Accumulate) = length(itr.itr) | ||||||||||||||
size(itr::Accumulate) = size(itr.itr) | ||||||||||||||
|
||||||||||||||
IteratorSize(::Type{Accumulate{F,I}}) where {F,I} = IteratorSize(I) | ||||||||||||||
IteratorSize(::Type{<:Accumulate{F,I}}) where {F,I} = IteratorSize(I) | ||||||||||||||
IteratorEltype(::Type{<:Accumulate}) = EltypeUnknown() | ||||||||||||||
|
||||||||||||||
# Rest -- iterate starting at the given state | ||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -793,8 +793,17 @@ end | |
@test collect(Iterators.accumulate(+, [1,2])) == [1,3] | ||
@test collect(Iterators.accumulate(+, [1,2,3])) == [1,3,6] | ||
@test collect(Iterators.accumulate(=>, [:a,:b,:c])) == [:a, :a => :b, (:a => :b) => :c] | ||
@test collect(Iterators.accumulate(+, (x for x in [true])))::Vector{Int} == [1] | ||
@test collect(Iterators.accumulate(+, (x for x in [true, true, false])))::Vector{Int} == [1, 2, 2] | ||
@test collect(Iterators.accumulate(+, (x for x in [true]), init=10.0))::Vector{Float64} == [11.0] | ||
@test length(Iterators.accumulate(+, [10,20,30])) == 3 | ||
@test size(Iterators.accumulate(max, rand(2,3))) == (2,3) | ||
@test Base.IteratorSize(Iterators.accumulate(max, rand(2,3))) === Base.IteratorSize(rand(2,3)) | ||
@test Base.IteratorEltype(Iterators.accumulate(*, ())) isa Base.EltypeUnknown | ||
end | ||
|
||
@testset "Base.accumulate" begin | ||
@test cumsum(x^2 for x in 1:3) == [1, 5, 14] | ||
@test cumprod(x + 1 for x in 1:3) == [2, 6, 24] | ||
@test accumulate(+, (x^2 for x in 1:3); init=100) == [101, 105, 114] | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a test for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some more tests are added in 78a6c44 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry that I missed that on first review: wouldn't this function need a compat annotation, like
cumsum
andcumprod
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching it. I added it in 7a4d7fe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, in the meantime I also thought about compat for the iterator version, and was sorry to have to ask you again another change, but you already made it :)