如果我有一个字典,如
my_dict = Dict(
"A" => "one",
"B" => "two",
"C" => "three"
)
反转键/值映射的最佳方法是什么?
答案 0 :(得分:13)
假设您不必担心重复的值会碰撞为关键值,您可以将map
与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"
答案 1 :(得分:11)
一种方法是使用理解来通过迭代键/值对来构建新词典,并沿途交换它们:
julia> Dict(value => key for (key, value) in my_dict)
Dict{String,String} with 3 entries:
"two" => "B"
"one" => "A"
"three" => "C"
交换键和值时,您可能需要记住,如果my_dict
具有重复值(例如"A"
),则新词典可能包含较少的键。此外,新词典中按键"A"
定位的值可能不是您期望的值(Julia的词典不会以任何容易确定的顺序存储其内容)。
答案 2 :(得分:4)
对于可能存在冲突值的词典进行了一段时间
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
使用此项,如果密钥重复,您将拥有一个包含所有值的列表,因此不会丢失任何数据,即
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]
答案 3 :(得分:2)
另一个好主意是本文的内容: https://discourse.julialang.org/t/is-something-like-reversed-dict-findall-x-x-house-cc-is-to-slow/16443
由于@ExpandingMan
,我特别喜欢这个解决方案:
dict = Dict(rand(Int, 10^5) .=> rand(Int, 10^5))
rdict = Dict(values(dict) .=> keys(dict))
或来自@bennedich
dict = Dict(rand(Int, 10^5) .=> rand(Int, 10^5))
rdict = Dict(v => k for (k,v) in dict)
答案 4 :(得分:1)
在Julia 1.x中(假设键和值之间存在双射):
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"
否则:
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"]