Jak zamienić klucze i wartości w skrócie?
Mam następujący hash:
{:a=>:one, :b=>:two, :c=>:three}
który chcę przekształcić w:
{:one=>:a, :two=>:b, :three=>:c}
Używanie map
wydaje się dość żmudne. Czy istnieje krótsze rozwiązanie?
Ruby ma pomocniczą metodę dla Hash, która pozwala traktować Hash tak, jakby był odwrócony (w istocie, umożliwiając dostęp do kluczy poprzez wartości):
{a: 1, b: 2, c: 3}.key(1)
=> :a
Jeśli chcesz zachować odwrócony hash, to Hash # invert powinno działać w większości sytuacji:
{a: 1, b: 2, c: 3}.invert
=> {1=>:a, 2=>:b, 3=>:c}
ALE...
Jeśli masz zduplikowane wartości, invert
spowoduje odrzucenie wszystkich wystąpień wartości oprócz ostatniego (ponieważ będzie zastępować nową wartość dla tego klucza podczas iteracji). Podobnie key
zwróci tylko pierwsze dopasowanie:
{a: 1, b: 2, c: 2}.key(2)
=> :b
{a: 1, b: 2, c: 2}.invert
=> {1=>:a, 2=>:c}
Jeśli więc twoje wartości są wyjątkowe, możesz użyć Hash#invert
. Jeśli nie, możesz zachować wszystkie wartości jako tablicę, na przykład:
class Hash
# like invert but not lossy
# {"one"=>1,"two"=>2, "1"=>1, "2"=>2}.inverse => {1=>["one", "1"], 2=>["two", "2"]}
def safe_invert
each_with_object({}) do |(key,value),out|
out[value] ||= []
out[value] << key
end
end
end
Uwaga: ten kod z testami jest teraz na GitHub .
Lub:
class Hash
def safe_invert
self.each_with_object({}){|(k,v),o|(o[v]||=[])<<k}
end
end
each_with_object
ma więcej sensu niżinject
.each_with_object({}){ |i,o|k,v = *i; o[v] ||=[]; o[v] << k}
... miłePewnie, że jest jeden! W Rubim zawsze jest krótszy sposób robienia rzeczy!
To całkiem proste, po prostu użyj
Hash#invert
:Zrobione!
źródło
Spowoduje to również obsługę zduplikowanych wartości.
źródło
Hash#inverse
daje Ci:podczas gdy wbudowana
invert
metoda jest po prostu zepsuta:źródło
Korzystanie z Array
Korzystanie z skrótu
źródło
Jeśli masz hash, w którym klucze są unikalne, możesz użyć Hash # invert :
To nie zadziała, jeśli masz nieunikalne klucze, ale tylko ostatnie widoczne klucze zostaną zachowane:
Jeśli masz skrót z nieunikalnymi kluczami, możesz zrobić:
Jeśli wartości skrótu są już tablicami, możesz:
źródło