说我有像这样的哈希
{"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]}
我希望它看起来像这样:
{"k1"=>"v1", "k2"=>"v2", "k3"=>"v3", "k4"=>"v4"}
有没有比这丑陋的inject
更简单的方法呢?
h1 = {"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]}
h2 = h1.inject({}){|h,v| h[v.first]=v.last.first; h}
答案 0 :(得分:8)
比你的“注入”解决方案稍微不那么难看:
h1 = {"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]}
h2 = Hash[*h1.map.flatten]
h2 # => {"k1"=>"v1", "k2"=>"v2", "k3"=>"v3", "k4"=>"v4"}
正如@the Tin Man在评论中指出的那样,如果您的值数组可能有多个元素,那么您需要做一些稍微不同的事情才能使其按预期工作:
h2 = Hash[*h1.map{|k,v|[k,v[0]]}.flatten]
h2 # => {"k1"=>"v1", "k2"=>"v2", "k3"=>"v3", "k4"=>"v4"}
答案 1 :(得分:3)
您可以使用简单的each
:
h = {"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]}
h.each { |k,v| h[k] = v[0] }
或者,如果您想制作副本,可以使用清洁工inject
:
flatter_h = h.inject({ }) { |x, (k,v)| x[k] = v[0]; x }
或者,如果您有each_with_object
可用(即Rails或Ruby 1.9):
flatter_h = h.each_with_object({ }) { |(k,v), x| x[k] = v[0] }
答案 2 :(得分:1)
对inject
的使用可能更有吸引力。 Hash#merge
是你的朋友:
hash = {"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]}
hash.inject({}) {|r,a| r.merge(a.first=>a.last.first)}
答案 3 :(得分:1)
>> h = {"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]}
>> Hash[h.map { |k, vs| [k, vs.first] }]
=> {"k1"=>"v1", "k2"=>"v2", "k3"=>"v3", "k4"=>"v4"}
答案 4 :(得分:1)
将来自@ tokland的答案的Hash[h.map { |k, v| [k, v.first] }]
语法与@ mu h.inject({ }) { |x, (k,v)| x[k] = v[0]; x }
中引入的数组解构语法相结合,我提出了我认为最干净的解决方案:
h1 = {"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]}
h2 = Hash[h1.map{|k,(v)| [k, v]}]