If I have a dictionary such as
my_dict = Dict(
"A" => "one",
"B" => "two",
"C" => "three"
)
What's the best way to reverse the key/value mappings?
If I have a dictionary such as
my_dict = Dict(
"A" => "one",
"B" => "two",
"C" => "three"
)
What's the best way to reverse the key/value mappings?
One way would be to use a comprehension to build the new dictionary by iterating over the key/value pairs, swapping them along the way:
julia> Dict(value => key for (key, value) in my_dict)
Dict{String,String} with 3 entries:
"two" => "B"
"one" => "A"
"three" => "C"
When swapping keys and values, you may want to keep in mind that if my_dict
has duplicate values (say "A"
), then the new dictionary may have fewer keys. Also, the value located by key "A"
in the new dictionary may not be the one you expect (Julia's dictionaries do not store their contents in any easily-determined order).
Assuming that you don't have to worry about repeated values colliding as keys, you could use map
with reverse
:
julia> my_dict = Dict("A" => "one", "B" => "two", "C" => "three")
Dict{String,String} with 3 entries:
"B" => "two"
"A" => "one"
"C" => "three"
julia> map(reverse, my_dict)
Dict{String,String} with 3 entries:
"two" => "B"
"one" => "A"
"three" => "C"
collect
on my_dict
first for Julia >= v1.x –
Roan made this a while back for dictionaries that may have clashing values
function invert_dict(dict, warning::Bool = false)
vals = collect(values(dict))
dict_length = length(unique(vals))
if dict_length < length(dict)
if warning
warn("Keys/Vals are not one-to-one")
end
linked_list = Array[]
for i in vals
push!(linked_list,[])
end
new_dict = Dict(zip(vals, linked_list))
for (key,val) in dict
push!(new_dict[val],key)
end
else
key = collect(keys(dict))
counter = 0
for (k,v) in dict
counter += 1
vals[counter] = v
key[counter] = k
end
new_dict = Dict(zip(vals, key))
end
return new_dict
end
using this if if a key becomes duplicate, you'll have a list with all values, so no data will be lost, i.e
julia> a = [1,2,3]
julia> b = ["a", "b", "b"]
julia> Dict(zip(a,b))
Dict{Int64,String} with 3 entries:
2 => "b"
3 => "b"
1 => "a"
julia> invert_dict(ans)
Dict{String,Array} with 2 entries:
"b" => Any[2,3]
"a" => Any[1]
In Julia 1.x (assuming a bijection between keys and values):
julia> D = Dict("A" => "one", "B" => "two", "C" => "three")
Dict{String,String} with 3 entries:
"B" => "two"
"A" => "one"
"C" => "three"
julia> invD = Dict(D[k] => k for k in keys(D))
Dict{String,String} with 3 entries:
"two" => "B"
"one" => "A"
"three" => "C"
Otherwise:
julia> D = Dict("A" => "one", "B" => "three", "C" => "three")
Dict{String,String} with 3 entries:
"B" => "three"
"A" => "one"
"C" => "three"
julia> invD = Dict{String,Vector{String}}()
Dict{String,Array{String,1}} with 0 entries
julia> for k in keys(D)
if D[k] in keys(invD)
push!(invD[D[k]],k)
else
invD[D[k]] = [k]
end
end
julia> invD
Dict{String,Array{String,1}} with 2 entries:
"one" => ["A"]
"three" => ["B", "C"]
Yet another good idea is what is done in this post: https://discourse.julialang.org/t/is-something-like-reversed-dict-findall-x-x-house-cc-is-to-slow/16443
Particularly, I liked a lot the solution, due to @ExpandingMan
:
dict = Dict(rand(Int, 10^5) .=> rand(Int, 10^5))
rdict = Dict(values(dict) .=> keys(dict))
or the one from @bennedich
dict = Dict(rand(Int, 10^5) .=> rand(Int, 10^5))
rdict = Dict(v => k for (k,v) in dict)
DSM answer adapted with bluesmoon comment becomes (checked in Julia 1.9):
julia> my_dict = Dict("A" => "one", "B" => "two", "C" => "three")
Dict{String, String} with 3 entries:
"B" => "two"
"A" => "one"
"C" => "three"
julia> Dict(map(reverse, collect(my_dict)))
Dict{String,String} with 3 entries:
"two" => "B"
"one" => "A"
"three" => "C"
Notice that map(reverse, collect(my_dict))
has type Vector{Pair{String, String}}
.
using BenchmarkTools
dic = Dict(zip(rand(10000),rand(10000)))
@benchmark Dict(map(reverse,collect(dic))) #403 us
@benchmark Dict(dic[i]=> i for i in keys(dic)) #2.84 ms
@benchmark Dict(reverse(i) for i in dic) #361 us
@benchmark Dict(value => key for (key, value) in dic) #351 us
@benchmark Dict(values(dic) .=> keys(dic)) #426 us
© 2022 - 2025 — McMap. All rights reserved.