2016-12-08 191 views
6

我有一个哈希:多个子哈希出一个哈希

hash = {"a_1_a" => "1", "a_1_b" => "2", "a_1_c" => "3", "a_2_a" => "3", 
     "a_2_b" => "4", "a_2_c" => "4"} 

什么让下面的子哈希值的最佳方式:

[{"a_1_a" => "1", "a_1_b" => "2", "a_1_c" => "3"}, 
{"a_2_a" => "3", "a_2_b" => "4", "a_2_c" => "4"}] 

我希望他们通过密钥分组,基于正则表达式/^a_(\d+)/。如果有人有任何建议,我会在原始散列中使用50个以上的键/值对,所以动态变化最好。

+3

这样的快速选择提供了可能阻碍其他的答案和短路那些答案仍在工作的第一个答案的。没有急于。在选择答案之前,许多人至少要等上几个小时,有些人的等待时间要长得多。 –

+1

好的,谢谢你的建议,我是新来的:) –

+0

其实有些人等了好几个月!别人从来没有做过LOL –

回答

7

如果你只关心中间组件,您可以使用group_by让你最那里的方式:

hash.group_by do |k,v| 
    k.split('_')[1] 
end.values.map do |list| 
    Hash[list] 
end 

# => [{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, {"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}] 

的最后一步是提取分组名单,并结合这些回所需的散列。

+1

这看起来像OP正在寻找什么。如果OP对这种事情感兴趣,也可以使它更简洁 'hash.group_by {| k,_ | k.split('_')[1]} .values.map(&:to_h)' – Damon

+0

正是我在找的东西,谢谢! –

4

代码

def partition_hash(hash) 
    hash.each_with_object({}) do |(k,v), h| 
    key = k[/(?<=_).+(?=_)/] 
    h[key] = (h[key] || {}).merge(k=>v) 
    end.values 
end 

hash = {"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3", "a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"} 
partition_hash(hash) 
    #=> [{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, 
    # {"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}] 

说明

的步骤如下。

enum = hash.each_with_object({}) 
    #=> #<Enumerator: {"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3", "a_2_a"=>"3", 
    #     "a_2_b"=>"4", "a_2_c"=>"4"}:each_with_object({})> 

此枚举的第一元素时产生并传递给块,和块变量使用并行分配计算。

(k,v), h = enum.next 
    #=> [["a_1_a", "1"], {}] 
k #=> "a_1_a" 
v #=> "1" 
h #=> {} 

并且执行块计算。

key = k[/(?<=_).+(?=_)/] 
    #=> "1" 
h[key] = (h[key] || {}).merge(k=>v) 
    #=> h["1"] = (h["1"] || {}).merge("a_1_a"=>"1") 
    #=> h["1"] = (nil || {}).merge("a_1_a"=>"1") 
    #=> h["1"] = {}.merge("a_1_a"=>"1") 
    #=> h["1"] = {"a_1_a"=>"1"} 

所以现在

h #=> {"1"=>{"a_1_a"=>"1"}} 

现在产生的enum的下一个值,并传递给块,并且执行下面的计算。

(k,v), h = enum.next 
    #=> [["a_1_b", "2"], {"1"=>{"a_1_a"=>"1"}}] 
k #=> "a_1_b" 
v #=> "2" 
h #=> {"1"=>{"a_1_a"=>"1"}} 

key = k[/(?<=_).+(?=_)/] 
    #=> "1" 
h[key] = (h[key] || {}).merge(k=>v) 
    #=> h["1"] = (h["1"] || {}).merge("a_1_b"=>"2") 
    #=> h["1"] = ({"a_1_a"=>"1"}} || {}).merge("a_1_b"=>"2") 
    #=> h["1"] = {"a_1_a"=>"1"}}.merge("a_1_b"=>"2") 
    #=> h["1"] = {"a_1_a"=>"1", "a_1_b"=>"2"} 

enum其余四个元件之后已被通过以下面已经返回块。

h #=> {"1"=>{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, 
    # "2"=>{"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}} 

最后一步是简单地提取值。

h.values 
    #=> [{"a_1_a"=>"1", "a_1_b"=>"2", "a_1_c"=>"3"}, 
    # {"a_2_a"=>"3", "a_2_b"=>"4", "a_2_c"=>"4"}]