我在ruby中有两个数组:
array_one = ["farmer_joe", "farmer_judy", "farmer_crazy_eyes", "farmer_joe"]
array_two = ["pigs", "chickens", "elephants", "cows"]
如果我使用zip函数,我会丢失重复值,即Farmer Joe的密钥对。
hash_one = Hash[array_one.zip array_two]
=> {"farmer_joe"=>"cows", "farmer_judy"=>"chickens", "farmer_crazy_eyes"=>"elephants"}
理想情况下,我想要一个允许我在一个漂亮的红宝石风味的oneline方法中克服这个功能的功能。也许这样的东西可以合并重复的键并将它们的值添加到数组中。
hash_one = Hash[array_one.super_special_zip array_two]
=> {"farmer_joe"=>["pigs","cows"], "farmer_judy"=>["chickens"], "farmer_crazy_eyes"=>["elephants"]}
是否有这样的super_special_zip
方法?或者有一个很好的理由为什么这首先是傻瓜差事?
答案 0 :(得分:3)
有三种标准方法可以做到这一点。
a1 = ["farmer_joe", "farmer_judy", "farmer_crazy_eyes", "farmer_joe"]
a2 = ["pigs", "chickens", "elephants", "cows"]
pairs = a1.zip(a2) # or [a1,a2].transpose
#=> [["farmer_joe", "pigs"], ["farmer_judy", "chickens"],
# ["farmer_crazy_eyes", "elephants"], ["farmer_joe", "cows"]]
<强> 1。使用Hash.new创建一个默认值为空数组的哈希
pairs.each_with_object(Hash.new { |h,k| h[k]=[] }) { |(f,l),h| h[f] << l }
# => {"farmer_joe"=>["pigs", "cows"], "farmer_judy"=>["chickens"],
# "farmer_crazy_eyes"=>["elephants"]}
这种变体(往往稍微快一点)是:
pairs.each_with_object({}) { |(f,l),h| (h[f] ||= []) << l }
<强> 2。使用Hash#update(也称为merge!)的形式,它采用一个块来确定合并的两个哈希中存在的键的值
pairs.each_with_object({}) { |(f,l),h| h.update(f=>[l]) { |_,o,n| o+n } }
#=> {"farmer_joe"=>["pigs", "cows"], "farmer_judy"=>["chickens"],
# "farmer_crazy_eyes"=>["elephants"]}
第3。使用Enumerable#group_by
h = pairs.group_by(&:first)
#=> {"farmer_joe"=>[["farmer_joe", "pigs"], ["farmer_joe", "cows"]],
# "farmer_judy"=>[["farmer_judy", "chickens"]],
# "farmer_crazy_eyes"=>[["farmer_crazy_eyes", "elephants"]]}
h.keys.each { |k| h[k] = h[k].map(&:last) }
h
#=> {"farmer_joe"=>["pigs", "cows"], "farmer_judy"=>["chickens"],
# "farmer_crazy_eyes"=>["elephants"]}
最后两行有很多替代品,一个是:
h.merge(h) { |*_,v| v.map(&:last) }
答案 1 :(得分:2)
一种方法
array_one = ["farmer_joe", "farmer_judy", "farmer_crazy_eyes", "farmer_joe"]
array_two = ["pigs", "chickens", "elephants", "cows"]
hash_one = {}
array_one.each_with_index do |farmer,i|
if hash_one.has_key?(farmer)
hash_one[farmer] << array_two[i]
else
hash_one[farmer] = [array_two[i]]
end
end
hash_one # => {"farmer_joe"=>["pigs", "cows"], "farmer_judy"=>["chickens"], "farmer_crazy_eyes"=>["elephants"]}
答案 2 :(得分:1)
另一种方法是(没有轨道)
a1 = ["farmer_joe", "farmer_judy", "farmer_crazy_eyes", "farmer_joe"]
a2= ["pigs", "chickens", "elephants", "cows"]
a1.zip(a2).group_by(&:first).map{|key, value| [key, value.map(&:last)]}.to_h
# => {"farmer_joe"=>["pigs", "cows"], "farmer_judy"=>["chickens"], "farmer_crazy_eyes"=>["elephants"]}