开发者

Ruby merge hashes putting keys into csv string

Is there a clever way to achieve the following in Ruby?

hash1 = { "a" => 1, "b" => 2, "d" => 3}
hash2 = { "a" => 4, "b" => 5, "c" => 7}
hash3 = { "a" => 4, "d" => 7, "e" => 9}
puts hash1.csvMerge(hash2).csvMerge(hash3)

with the output being:

{ "a" => "1,4,4",
  "b" => "2,5,0",
  "c" => "0,7,0",
  "d" => "3,0,7",
  "e" => "0,0,9" }

What I'm trying to do is merge a bunch of Ruby hashes, in practice I have over a dozen, into a single hash where the values are combined into a 开发者_如何学JAVAcomma separated string.


hash1.merge(hash2){|key, oldval, newval| [oldval,newval].join(",")}
 => {"a"=>"1,4", "b"=>"2,5", "d"=>3, "c"=>7} 


hashes = [hash1, hash2, hash3]
keys = hashes.inject({}){|hh, h| hh = hh.merge(h); hh}.keys   # the set of all keys #
default_hash = keys.inject({}){|d, k| d[k] = 0; d}    # hash with value 0 for all keys #
complemented_hashes = hashes.map{|h| default_hash.merge(h)} # missing values filled in #

p Hash[complemented_hashes.map{|h| h.to_a}.flatten(1).group_by{|k, v| k}.
map{|k, v| [k, v.map{|k, v| v}.join(",")]}]


I dont know if this has performance issues

hashes = [hash1, hash2, hash3]
hash_with_all_keys = {}
hashes.each{|hash| hash_with_all_keys.merge!(hash)}
keys = hash_with_all_keys.keys
result_hash_mapping = keys.map do |key|
  value = hashes.map{|hash| hash[key].to_i}.join(",")
  [key, value]
end
result_hash = Hash[result_hash_mapping]

I could have replaced lines 2 to 4 with keys = hashes.inject({}){|merge_hash, hash| merge_hash.merge(hash)}.keys but I find it hard to read.


hash1 = { "a" => 1, "b" => 2, "d" => 3}
hash2 = { "a" => 4, "b" => 5, "c" => 7}
hash3 = { "a" => 4, "d" => 7, "e" => 9}

hashes = [hash1, hash2, hash3]
hashes.each{|h| h.each{|k,v| h[k] = v.to_s }}
res = hashes.inject{|m,h| m.merge(h){|k,old,new| "#{old},#{new}" }} #merge and glue

p res
#=> {"a"=>"1,4,4", "b"=>"2,5", "d"=>"3,7", "c"=>"7", "e"=>"9"}


Functional approach:

hashes = [hash1, hash2, hash3]
result = Hash[hashes.flat_map(&:keys).uniq.map do |key|
  [key, hashes.map { |h| h[key] || 0 }.join(",")]
end]
#=> {"a"=>"1,4,4", "b"=>"2,5,0", "c"=>"0,7,0", "d"=>"3,0,7", "e"=>"0,0,9"}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜