2011-06-01 149 views
1

说我有这样的红宝石哈希与数组值

{"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} 

回答

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] } 
+0

好点啊。你赢了;) – 2011-06-01 02:16:10

+0

@Ryan:你应该离开你的了,如果你想离开原作,这是合理的解决方案。 – 2011-06-01 02:23:55

+0

等一下,我们可以改变吗?那么该死:) – zetetic 2011-06-01 02:29:36

1

也许更有吸引力的使用injectHash#merge是你的朋友:

hash = {"k1"=>["v1"], "k2"=>["v2"], "k3"=>["v3"], "k4"=>["v4"]} 
hash.inject({}) {|r,a| r.merge(a.first=>a.last.first)} 
+1

使用'| r,(k,v)|'会更有吸引力,我在这个符号中添加了几个选项来回答我的问题。 – 2011-06-01 02:43:21

+0

嗯,这个对我来说实际上读起来有点丑陋=) – maerics 2011-06-01 02:59:25

+0

@mu:不错,我不知道你可以通过这种方式获得关键/价值的参数。 – zetetic 2011-06-01 03:25:12

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铁皮人在评论中指出,如果你的价值阵列可能有不止一个元素那么你就需要做一些事情略有不同,它的工作如预期:

h2 = Hash[*h1.map{|k,v|[k,v[0]]}.flatten] 
h2 # => {"k1"=>"v1", "k2"=>"v2", "k3"=>"v3", "k4"=>"v4"} 
+0

+1。太棒了。 – zetetic 2011-06-01 03:27:36

+0

如果值数组有多个元素,它将不起作用。 – 2011-06-01 05:05:23

+1

只适用于1.8,其中'map'返回'Array'。在1.9中,你需要'Hash [* h1.map.to_a.flatten]',因为'map'给你一个'Enumerator'。否则,非常酷。 – Amadan 2011-06-01 08:22:08

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"} 
1

组合来自@ tokland的答案Hash[h.map { |k, v| [k, v.first] }]语法与@亩的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]}]