How do I sort a dictionary by its keys?

I want to sort this by its keys:

5-element Dictionaries.HashDictionary{Int64,Any}
 4 │ 0.2199244
 2 │ 0.2000908
 3 │ 0.19014
 5 │ 0.2099752
 1 │ 0.1798696

How did you construct the dictionary? Maybe include code to make it.

For normal Dictionaries

dict = Dict(i => rand() for i in 1:5)
sort(collect(dict), by = x->x[1])
1 Like
q = 0.2
c = 1.1
p = [0.18, 0.2, 0.19, 0.22, 0.21]
@assert sum(p) == 1

function Y()
    return ceil(Int, rand()*5)
end
# Y()
function X()
    while true
        y = Y()
        if rand() <= (p[y]/(q*c)) # if we use q*c without parens the instability breaks our results.
            return y
        end
    end
end
# X()

n = 10^7
@time a = [X() for i in 1:n]

using SplitApplyCombine
dict = map(x -> length(x)/n, group(a))

Note that Dictionaries.HashDictionary has no order defined (similar to Dict), so the question does not make sense.

You can collect key-value pairs in a vector and sort them though, as @xiaodai suggested.

2 Likes

You may also want to look at DataStructures.jl which has a SortedDict struct, which will handle this for you.

8 Likes

I needed to sort(collect(pairs(d)), by=x->x[1]). See GitHub - andyferris/Dictionaries.jl: An alternative interface for dictionaries in Julia, for improved productivity and performance .

If someone need to make an ordered dictionary, it is a bit better to sort then create the ordered dictionary.

using OrderedCollections
using BenchmarkTools

unordered = Dict(i => rand() for i = 1:1000)

@btime begin
    sorted = OrderedDict(unordered)
    sort!(sorted)
 end
# 68.958 μs (24 allocations: 113.55 KiB)

@btime ordered = OrderedDict(sort(collect(unordered), by=x->x[1]))
# 60.121 μs (22 allocations: 112.92 KiB)

You can save an allocation and a little time by sorting the collected vector in place

ordered = OrderedDict(sort!(collect(unordered), by=x->x[1]))

and a slight amount of typing with

ordered = OrderedDict(sort!(collect(unordered), by=first))
3 Likes
using Dictionaries
julia> let d = Dictionary(rand(5), rand(5))
           getindices(d, sortperm(keys(d))) 
       end
5-element Dictionary{Float64, Float64}
 0.3303619285549789 │ 0.6295079531224393
 0.6532413238779383 │ 0.25149701734258545
   0.74806859304317 │ 0.8964936651264518
 0.9116373283422051 │ 0.011738639576267418
 0.9131045316602528 │ 0.5310761199500899

In Julia 1.10.4, by simply doing: sort(d, by=first), it outputs an OrderedCollections.OrderedDic object:

d = Dict(1:5 .=> rand(5))
sort(d, by=first)

PS:
The package OrderedCollections.jl is not installed.

If the package OrderedCollections is doing that, that sounds like type piracy. Edit: that’s indeed the case: Type piracy? · Issue #25 · JuliaCollections/OrderedCollections.jl · GitHub

4 Likes