ruby on rails - hashes - La forma más limpia de crear un hash desde una matriz
ruby array of hashes (5)
¿el más corto?
# ''Region'' is a sample class here
# you can put ''self.to_hash'' method into any class you like
class Region < ActiveRecord::Base
def self.to_hash
Hash[*all.map{ |x| [x.id, x] }.flatten]
end
end
Me parece toparse con esto muy a menudo. Necesito construir un Hash a partir de una matriz usando un atributo de cada objeto en la matriz como la clave.
Digamos que necesito un hash de ejemplo. Utiliza los objecs de ActiveRecord codificados por sus identificadores. Forma común:
ary = [collection of ActiveRecord objects]
hash = ary.inject({}) {|hash, obj| hash[obj.id] = obj }
De otra manera:
ary = [collection of ActiveRecord objects]
hash = Hash[*(ary.map {|obj| [obj.id, obj]}).flatten]
Dream Way: podría y podría crear esto yo mismo, pero ¿hay algo en Ruby o Rails que pueda hacer esto?
ary = [collection of ActiveRecord objects]
hash = ary.to_hash &:id
#or at least
hash = ary.to_hash {|obj| obj.id}
En caso de que alguien tenga una matriz simple
arr = ["banana", "apple"]
Hash[arr.map.with_index.to_a]
=> {"banana"=>0, "apple"=>1}
Instala la gema Ruby Facets y usa su Array.to_h .
Puedes agregar to_hash a Array tú mismo.
class Array
def to_hash(&block)
Hash[*self.map {|e| [block.call(e), e] }.flatten]
end
end
ary = [collection of ActiveRecord objects]
ary.to_hash do |element|
element.id
end
Ya hay un método en ActiveSupport que hace esto.
[''an array'', ''of active record'', ''objects''].index_by(&:id)
Y solo para que quede registrado, aquí está la implementación:
def index_by
inject({}) do |accum, elem|
accum[yield(elem)] = elem
accum
end
end
Que podría haber sido refactorizado en (si estás desesperado por frases ingeniosas):
def index_by
inject({}) {|hash, elem| hash.merge!(yield(elem) => elem) }
end