Rails将哈希数组映射到单个哈希


91

我有这样一个哈希数组:

 [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]

我正在尝试将此映射到单个哈希,如下所示:

{"testPARAM2"=>"testVAL2", "testPARAM1"=>"testVAL1"}

我已经实现了

  par={}
  mitem["params"].each { |h| h.each {|k,v| par[k]=v} } 

但是我想知道是否有可能以更惯用的方式进行此操作(最好不使用局部变量)。

我怎样才能做到这一点?

Answers:


159

您可以撰写Enumerable#reduceHash#merge完成您想要的。

input = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]
input.reduce({}, :merge)
  is {"testPARAM2"=>"testVAL2", "testPARAM1"=>"testVAL1"}

减少数组的排序就像在每个元素之间插入一个方法调用一样。

例如[1, 2, 3].reduce(0, :+)0 + 1 + 2 + 3和给6

在我们的示例中,我们执行了类似的操作,但是使用了合并功能,该功能合并了两个哈希。

[{:a => 1}, {:b => 2}, {:c => 3}].reduce({}, :merge)
  is {}.merge({:a => 1}.merge({:b => 2}.merge({:c => 3})))
  is {:a => 1, :b => 2, :c => 3}

1
谢谢,这是一个很好的答案:)非常好的解释!
巴特·普拉塔克

40
input.reduce(&:merge)就足够了。
redgetan 2014年

@redgetan与有什么不同input.reduce(:merge)吗?
David van Geest,2015年

1
@David van Geest:在这种情况下,它们是等效的。此处使用的一元“&”号会在符号之外构建一个块。但是,reduce有一个接受符号的特殊情况。我想避免使用一元&符来简化示例,但是redgetan正确,因为在这种情况下初始值是可选的。
cjhveal 2015年

1
请注意,如果使用merge!代替merge它,则会修改第一个哈希(您可能不需要),但不会为每个新合并创建中间哈希。
Phrogz '16

50

怎么样:

h = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]
r = h.inject(:merge)

该方案实际上与Joshua回答的方案相同,但是对所有散列重复使用#merge(方法名称作为符号传递)(将注入作为运算符注入到项目之间)。请参阅#inject
shigeya

2
为什么不需要h.inject(&:merge)中的与号?
多纳托2015年

5
因为inject方法也接受符号作为参数,所以也要解释为方法名称。这是注入功能。
shigeya 2015年

9

使用#inject

hashes = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]
merged = hashes.inject({}) { |aggregate, hash| aggregate.merge hash }
merged # => {"testPARAM1"=>"testVAL1", "testPARAM2"=>"testVAL2"}

0

在这里,您可以使用Enumerable类中的injectreduce,因为它们都是彼此的别名,因此两者都不会对性能有所帮助。

 sample = [{"testPARAM1"=>"testVAL1"}, {"testPARAM2"=>"testVAL2"}]

 result1 = sample.reduce(:merge)
 # {"testPARAM1"=>"testVAL1", "testPARAM2"=>"testVAL2"}

 result2 = sample.inject(:merge)
 # {"testPARAM1"=>"testVAL1", "testPARAM2"=>"testVAL2"}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.