2013-04-02 7 views
22

Mam tablicę obiektów:Konwersja tablicę obiektów do Hash z polem jako kluczowy

[ 
    #<User id: 1, name: "Kostas">, 
    #<User id: 2, name: "Moufa">, 
    ... 
] 

I chcę do konwersji na hash z id jak przyciski i obiektów jak wartości . Teraz robię to tak tak ale wiem istnieje lepszy sposób:

users = User.all.reduce({}) do |hash, user| 
    hash[user.id] = user 
    hash 
end 

oczekiwany wynik:

{ 
    1 => #<User id: 1, name: "Kostas">, 
    2 => #<User id: 2, name: "Moufa">, 
    ... 
} 
+0

@SergioTulentsev, szukałem w [Enumerable # group_by] (http: // www. ruby-doc.org/core-1.9.3/Enumerable.html#method-i-group_by) i to było prawie to, czego szukam. Po prostu pomyślałem, że istnieje jego wersja zamiast budować tablice wartości, jest bardziej agresywna i zachowuje tylko jedną wartość. – Kostas

Odpowiedz

44
users_by_id = User.all.map { |u| [u.id, u] }.to_h 

Przy zastosowaniu szyn (który Twój kod wygląda), ActiveSupport zapewnia Enumerable#index_by:

users_by_id = User.all.index_by(&:id) 
+0

Ja osobiście wolę sposób 'mash' zamiast "Hash [...]". Czyta się czystsze, bardziej rubinowo. – Kostas

+1

Wierzę, że Twój Ruby> = 2.1 wymaga niewielkiej korekty, chcesz .to_h nie .to_a, np. 'users = User.all.map {| u | [u.id, u]} .to_h' – Tron

4

Dostaniesz nieznacznie lepszy kod za pomocą each_with_object zamiast reduce .

users = User.all.each_with_object({}) do |user, hash| 
    hash[user.id] = user 
end 
+0

Czy ponownie przejdziemy do ścieżki inject/each_with_object/Hash/mash? :-) http://bugs.ruby-lang.org/issues/show/666 – tokland

+0

@tokland: Tak, to była pierwsza myśl w mojej głowie, kiedy zobaczyłem twój komentarz :) –

Powiązane problemy