Skip to content

Commit

Permalink
Merge pull request #108 from maltezfaria/master
Browse files Browse the repository at this point in the history
lazy reverse iteration of `OrderedDict`
  • Loading branch information
Tokazama authored Nov 22, 2023
2 parents c3687a8 + 702507b commit 87a2334
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "OrderedCollections"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.2"
version = "1.6.3"

[compat]
julia = "1.6"
Expand Down
7 changes: 7 additions & 0 deletions src/little_dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ function Base.iterate(dd::LittleDict, ii=1)
return (dd.keys[ii] => dd.vals[ii], ii+1)
end

# lazy reverse iteration
function Base.iterate(rdd::Iterators.Reverse{<:LittleDict}, ii=length(rdd.itr.keys))
dd = rdd.itr
ii < 1 && return nothing
return (dd.keys[ii] => dd.vals[ii], ii-1)
end

function merge(d1::LittleDict, others::AbstractDict...)
return merge((x,y)->y, d1, others...)
end
Expand Down
15 changes: 15 additions & 0 deletions src/ordered_dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,21 @@ function iterate(t::OrderedDict, i)
return (Pair(t.keys[i], t.vals[i]), i+1)
end

# lazy reverse iteration
function iterate(rt::Iterators.Reverse{<:OrderedDict})
t = rt.itr
t.ndel > 0 && rehash!(t)
n = length(t.keys)
n < 1 && return nothing
return (Pair(t.keys[n], t.vals[n]), n - 1)
end
function iterate(rt::Iterators.Reverse{<:OrderedDict}, i)
t = rt.itr
i < 1 && return nothing
return (Pair(t.keys[i], t.vals[i]), i - 1)
end


function _merge_kvtypes(d, others...)
K, V = keytype(d), valtype(d)
for other in others
Expand Down
7 changes: 7 additions & 0 deletions src/ordered_set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ function iterate(s::OrderedSet, i)
return (s.dict.keys[i], i+1)
end

# lazy reverse iteration
function iterate(rs::Iterators.Reverse{<:OrderedSet}, i = length(rs.itr))
s = rs.itr
i < 1 && return nothing
return (s.dict.keys[i], i-1)
end

pop!(s::OrderedSet) = pop!(s.dict)[1]
popfirst!(s::OrderedSet) = popfirst!(s.dict)[1]

Expand Down
15 changes: 14 additions & 1 deletion test/test_little_dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -559,5 +559,18 @@ end # @testset LittleDict
map!(v->v-1, values(testdict))
@test testdict[:a] == 0
@test testdict[:b] == 1
end
end

@testset "lazy reverse iteration" begin
ks = collect('a':'z')
vs = collect(0:25)
ld = LittleDict(ks, vs)
pass = true
for (n,(k,v)) in enumerate(Iterators.reverse(ld))
pass &= reverse(ks)[n] == k
pass &= reverse(vs)[n] == v
end
@test pass
end

end
14 changes: 13 additions & 1 deletion test/test_ordered_dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -456,10 +456,22 @@ using OrderedCollections, Test
end

@testset "ordered access" begin
od = OrderedDict(:a=>1, :b=>2, :c=>3)
od = OrderedDict(:a=>1, :b=>2, :c=>3)
@test popfirst!(od) == (:a => 1)
@test :a keys(od)
@test pop!(od) == (:c => 3)
@test :c keys(od)
end

@testset "lazy reverse iteration" begin
ks = collect('a':'z')
vs = collect(0:25)
od = OrderedDict(k=>v for (k,v) in zip(ks, vs))
pass = true
for (n,(k,v)) in enumerate(Iterators.reverse(od))
pass &= reverse(ks)[n] == k
pass &= reverse(vs)[n] == v
end
@test pass
end
end # @testset OrderedDict
9 changes: 9 additions & 0 deletions test/test_ordered_set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -259,4 +259,13 @@ using OrderedCollections, Test
@test issorted(ox; rev=true)
end

@testset "lazy reverse iteration" begin
ks = collect('a':'z')
os = OrderedSet(ks)
pass = true
for (n,k) in enumerate(Iterators.reverse(os))
pass &= reverse(ks)[n] == k
end
@test pass
end
end # @testset OrderedSet

2 comments on commit 87a2334

@Tokazama
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/95818

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.6.3 -m "<description of version>" 87a2334a0d0be7e6fd0d3f6dad90687131c758e6
git push origin v1.6.3

Please sign in to comment.