【问题标题】:How to reverse a dictionary in Julia?如何在 Julia 中反转字典?
【发布时间】:2017-04-03 07:30:09
【问题描述】:

如果我有一本字典,比如

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

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

【问题讨论】:

  • 您是否需要担心两个不同的键映射到相同的值?

标签: dictionary julia


【解决方案1】:

另一个好主意是在这篇文章中做了什么: 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)

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      为可能有冲突值的字典做了一段时间

      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]
      

      【讨论】:

        【解决方案4】:

        假设您不必担心重复值作为键冲突,您可以使用 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"
        

        【讨论】:

        • 这是最好的答案!
        • @DSM:你如何为 Julia v1.x 做到这一点?
        • 我认为这在 Julia 版本 1.1.1 中不起作用。我收到一个错误“字典上没有定义地图”。
        【解决方案5】:

        一种方法是使用推导式通过迭代键/值对来构建新字典,并在此过程中交换它们:

        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 的字典不会以任何容易确定的顺序存储它们的内容)。

        【讨论】:

          猜你喜欢
          • 2016-07-14
          • 2014-07-22
          • 2019-04-09
          • 2021-08-21
          • 2016-09-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多