2017-02-09 245 views
1

的多个GROUP_BY我有一个这样的阵列:红宝石阵列

[{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}, {:a=>"2017-01-02", :b=>"5", :c=>"1"}] 

如果,例如,I组与键阵列 “:A”,其结果是:

p = y.group_by { |g| g[:a]} 

=> {"2017-01-01"=>[{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}], "2017-01-02"=>[{:a=>"2017-01-02", :b=>"5", :c=>"1"}]} 

现在我想分组为每个“:一个”的关键“:b”像:

=> {"2017-01-01"=>["2" => [{:a => "2017-01-01", :b => "2", :c => "1" }], ... } 

我该怎么办?提前致谢。

编辑

多个组由... 1°GROUP_BY一个,2°GROUP_BY B的1°的结果,等等。

y.group_by {|g| g[:a]}.map do |k,v| 
[ 
    k, v.group_by { |d| d[:b] }.map do |p,q| 
    [p, q.group_by { |f| f[:c] }] 
    end.to_h 
] 
end.to_h 
+0

1.'[:a => ...'不是有效的Ruby对象。请编辑更正。 2.“......”代表什么并不明显。请将所有'...'替换为您希望用作示例输出的值。 3.当你给一个例子(通常)给每个输入对象分配一个变量(例如'arr = [{:a => ... ...'),以便读者可以在答案中引用这些变量(这里只是一个)评论而不必定义它们。 –

回答

4

快速应答,使用上述代码:

y = [{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}, {:a=>"2017-01-02", :b=>"5", :c=>"1"}] 
p = y.group_by { |g| g[:a]} 
q = p.map {|date, list| [date, list.group_by {|g| g[:b]}]}.to_h 

这给出了所期望的结果:

q == { 
    "2017-01-01" => { 
    "2"=> [ 
     {:a=>"2017-01-01", :b=>"2", :c=>"1"}, 
     {:a=>"2017-01-01", :b=>"2", :c=>"2"} 
    ] 
    }, 
    "2017-01-02" => { 
    "5"=> [ 
     {:a=>"2017-01-02", :b=>"5", :c=>"1"} 
    ] 
    } 
} 

这有点奇怪的散列映射到阵列的列表,然后将其转换回一个散列(使用to_h)的图案可以稍微如果您使用的是Rails v4.2+ project工作,通过使用Hash#transform_values被简化:

p.transform_values {|list| list.group_by {|g| g[:b]}} 

然而,就此而言,通常认为是不好的做法是操作像这样的复杂的嵌套散列对象。如果你的代码太复杂了,你可能希望考虑重新设计它的工作方式,采用更加面向对象的方式。

+0

非常感谢您的回答。 – sirion1987

+0

我会向您提出另一个问题。如果我想通过第二个过滤器添加其他group_,我该如何继续? – sirion1987

+0

额外的'group_by'?你的意思是最终结果如下:'{“2017-01-01”=> {“2”=> {“1”=> {:a =>“2017-01-01”,:b =>“ 2“,:c =>”1“} ....'? –

1

我认为,从可能的解决方案的几个是:

y = [ 
    { 
    :a=>"2017-01-01", 
    :b=>"2", 
    :c=>"1" 
    }, 
    { 
    :a=>"2017-01-01", 
    :b=>"2", 
    :c=>"2" 
    }, 
    { 
    :a=>"2017-01-02", 
    :b=>"5", 
    :c=>"1" 
    } 
] 

第一:

y.group_by { |g| [g[:a], g[:b]] } 

,但结果将显得:

#=> {["2017-01-01", "2"]=>[{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}], ["2017-01-02", "5"]=>[{:a=>"2017-01-02", :b=>"5", :c=>"1"}]} 

和第二个:

y.group_by { |g| g[:a] }.map do |key, value| 
    [key, value.group_by { |g| g[:b] }] 
end.to_h 

#=> {"2017-01-01"=>{"2"=>[{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}]}, "2017-01-02"=>{"5"=>[{:a=>"2017-01-02", :b=>"5", :c=>"1"}]}}