2016-11-19 15 views
7

Jeśli mam słownika takiego jakJak odwrócić słownik w Julia?

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

Jaki jest najlepszy sposób, aby odwrócić mapowania klucz/wartość?

+0

Czy musisz martwić się dwoma różnymi mapami klawiszy o tej samej wartości, czy nie? – DSM

Odpowiedz

11

Jednym ze sposobów byłoby użyć zrozumieniem zbudować nowego słownika przez iteracja ciągu par klucz/wartość, zamieniając je na drodze:

julia> Dict(value => key for (key, value) in my_dict) 
Dict{String,String} with 3 entries: 
    "two" => "B" 
    "one" => "A" 
    "three" => "C" 

Podczas wymiany kluczy i wartości, może chcesz zachować pamiętając, że jeśli my_dict ma zduplikowane wartości (na przykład "A"), nowy słownik może mieć mniej kluczy. Ponadto wartość znaleziona przez klucz "A" w nowym słowniku może nie być tym, czego się spodziewasz (słowniki Julii nie przechowują swoich treści w łatwo ustalonej kolejności).

14

Zakładając, że nie trzeba się martwić o powtarzających się wartości kolidujących jak klucze, można użyć map z 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" 
+0

To najlepsza odpowiedź! –

4

dokonał tego jakiś czas temu do słowników, które mogą mieć wartości zderzeniu

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 

używając tego, jeśli klucz staje się duplikatem, będziesz mieć listę z wszystkimi wartościami, więc żadne dane nie zostaną utracone, tj.

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]