如何倒转朱莉娅的字典?

时间:2016-11-19 14:43:54

标签: dictionary julia

如果我有一个字典,如

my_dict = Dict(
    "A" => "one",
    "B" => "two",
    "C" => "three"
  )

反转键/值映射的最佳方法是什么?

5 个答案:

答案 0 :(得分:13)

假设您不必担心重复的值会碰撞为关键值,您可以将mapreverse一起使用:

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"]