Dobra, więc oto oferta, od wieków szukam rozwiązania tego problemu i chociaż jest ich wielu, wydaje się, że nie wykonują pracy, której szukam.
Zasadniczo mam taką strukturę tablicy
["item 1", "item 2", "item 3", "item 4"]
Chcę przekonwertować to na skrót, więc wygląda to tak
{ "item 1" => "item 2", "item 3" => "item 4" }
tzn. elementy, które znajdują się w indeksach „parzystych” są kluczami, a elementy w indeksach „nieparzystych” są wartościami.
Wszelkie pomysły, jak to zrobić czysto? Podejrzewam, że metodą brutalnej siły byłoby po prostu wyciągnięcie wszystkich parzystych indeksów do oddzielnej tablicy, a następnie zapętlenie ich w celu dodania wartości.
*
nazywany jest operatorem splat . Pobiera tablicę i przekształca ją w dosłowną listę elementów. Więc*[1,2,3,4]
=>1, 2, 3, 4
. W tym przykładzie powyższe jest równoważne z działaniemHash["item 1", "item 2", "item 3", "item 4"]
. IHash
ma[]
metodę, która akceptuje listę argumentów (tworząc klucze indeksów nieparzystych i wartości indeksów nieparzystych), aleHash[]
nie akceptuje tablicy, więc używamy jej do splatania*
.Hash[a.each_slice(2).to_a]
.Ruby 2.1.0 wprowadził
to_h
metodę Array, która robi to, czego potrzebujesz, jeśli twoja oryginalna tablica składa się z tablic par klucz-wartość: http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-to_h .źródło
bar
musi to być symbol, a symbol:2
powinien być liczbą całkowitą. Poprawione jest więc twoje wyrażeniea = [[:foo, 1], [:bar, 2]]
).Po prostu użyj
Hash.[]
z wartościami w tablicy. Na przykład:źródło
*arr
konwertujearr
na listę argumentów, więc wywołuje to[]
metodę Hash z zawartością arr jako argumentów.Lub jeśli masz tablicę
[key, value]
tablic, możesz:źródło
Hash[*arr]
{ [1, 2] => [3, 4] }
. A ponieważ tytuł pytania brzmi „Array to Hash”, a wbudowana metoda „Hash to Array”:{ 1 => 2, 3 => 4}.to_a # => [[1, 2], [3, 4]]
myślałem, że więcej niż jeden może skończyć tutaj, próbując uzyskać odwrotność wbudowanej metody „Hash to Array”. Właściwie tak właśnie tu się skończyłem.Hash[arr]
wykona za ciebie pracę.#inject
metody. Z#merge!
,#each_with_object
powinien był zostać użyty. Jeśli#inject
jest nalegany,#merge
zamiast#merge!
powinien był być używany.Właśnie tego szukałem, przeglądając to:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}
źródło
merge
, konstruuje i odrzuca nowy skrót dla iteracji w pętli i jest bardzo wolny. Jeśli masz tablicę skrótów, spróbuj[{a:1},{b:2}].reduce({}, :merge!)
zamiast tego - scala wszystko w ten sam (nowy) skrót..reduce(&:merge!)
[{a: 1}, {b: 2}].reduce(&:merge!)
ocenia na{:a=>1, :b=>2}
[{a: 1}, {b: 2}].reduce(&:merge!)
jest taki sam jak ten,[{a: 1}, {b: 2}].reduce { |m, x| m.merge(x) }
który jest taki sam jak[{b: 2}].reduce({a: 1}) { |m, x| m.merge(x) }
.Enumerator
obejmujeEnumerable
. Ponieważ2.1
,Enumerable
posiada również metodę#to_h
. Dlatego możemy napisać:Ponieważ
#each_slice
bez bloku daje namEnumerator
i zgodnie z powyższym wyjaśnieniem możemy wywołać#to_h
metodę naEnumerator
obiekcie.źródło
Możesz spróbować w ten sposób dla pojedynczej tablicy
dla tablicy tablic
źródło
lub jeśli nienawidzisz
Hash[ ... ]
:lub, jeśli jesteś leniwym fanem zepsutego programowania funkcjonalnego:
źródło
Hash[ ... ]
ale chcesz użyć go jako metody powiązanej (tak jak możesz to zrobićto_h
), możesz połączyć sugestie Borisa i napisać:arr.each_slice( 2 ).map { |e| e }.tap { |a| break Hash[a] }
Wszystkie odpowiedzi zakładają, że tablica początkowa jest unikalna. OP nie określił, jak obsługiwać tablice ze zduplikowanymi wpisami, które skutkują powieleniem kluczy.
Spójrzmy na:
Stracisz
item 1 => item 2
parę, ponieważ jest ona zastąpiona bijitem 1 => item 5
:Wszystkie metody, w tym
reduce(&:merge!)
skutkują tym samym usunięciem.Możliwe jednak, że tego właśnie oczekujesz. Ale w innych przypadkach prawdopodobnie
Array
zamiast tego chcesz uzyskać wynik o wartości:Naiwnym sposobem byłoby utworzenie zmiennej pomocniczej, skrótu o wartości domyślnej, a następnie wypełnienie jej w pętli:
Może być możliwe użycie
assoc
ireduce
wykonanie powyżej w jednym wierszu, ale staje się to znacznie trudniejsze do przemyślenia i przeczytania.źródło