简体   繁体   中英

Ruby : Generate a Hash of Hashes from an Array of Hashes

I have the following

friends = [{ name: "Jack", attr1:"def", attr2:"def" }, { name: "Jill", attr1:"def", attr2:"def" }]

I want to convert the above representation into a hash of hashes like this

friends = { "Jack" => { attr1: "def", attr2:"def" }, "Jill" => { attr1: "def", attr2: "def" } }

Any elegant way of doing this in Ruby ?

Hash[friends.map { |f| _f = f.dup; [_f.delete(:name), _f] }]
# => {"Jack"=>{:attr1=>"def", :attr2=>"def"}, "Jill"=>{:attr1=>"def", :attr2=>"def"}}
friends.each_with_object({}) do |f, o|
    f = f.dup
    o[f.delete :name] = f
end
hash = {}
friends.each{|h| hash[h.delete(:name)] = h }
# => {"Jack"=>{:attr1=>"def", :attr2=>"def"}, "Jill"=>{:attr1=>"def", :attr2=>"def"}}

When you want to transform one array into another, use collect :

friends = Hash[
  friends.collect do |f|
    _f = f.dup
    name = _f.delete(:name)
    [ name, _f ]
  end
]

You can create a new hash easily using Hash[] and provide it an array with a series of key/value pairs in it. In this case the name field is removed from each.

If we understand "elegant" as the way to write concise code by leveraging reusable abstractions, I'd write:

require 'active_support/core_ext/hash'
require 'facets/hash'
friends.mash { |f| [f[:name], f.except(:name)] }

No need to add gem dependencies for these two fairly big libraries, you can always implement the individual methods in your extensions library.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM