【发布时间】:2017-04-03 07:30:09
【问题描述】:
如果我有一本字典,比如
my_dict = Dict(
"A" => "one",
"B" => "two",
"C" => "three"
)
反转键/值映射的最佳方法是什么?
【问题讨论】:
-
您是否需要担心两个不同的键映射到相同的值?
标签: dictionary julia
如果我有一本字典,比如
my_dict = Dict(
"A" => "one",
"B" => "two",
"C" => "three"
)
反转键/值映射的最佳方法是什么?
【问题讨论】:
标签: dictionary julia
另一个好主意是在这篇文章中做了什么: 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)
【讨论】:
在 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"]
【讨论】:
为可能有冲突值的字典做了一段时间
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]
【讨论】:
假设您不必担心重复值作为键冲突,您可以使用 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"
【讨论】:
一种方法是使用推导式通过迭代键/值对来构建新字典,并在此过程中交换它们:
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 的字典不会以任何容易确定的顺序存储它们的内容)。
【讨论】: