使用类似数据减少和分组哈希

时间:2017-07-20 05:53:56

标签: ruby-on-rails ruby

我正在尝试在以下结构中对哈希进行分组

{
  name: "cardio", 
  data: [["06:00", 999], ["09:00", 154], ["10:00", 1059], ["11:00", 90]]
}
{
  name: "swimming", 
  data: [["10:00",90 ], ["11:00", 50]]
}

目前这是我的数据。

 [{"average_attendance"=>0.999e3, "sum_attendance"=>999, "place_type"=>"cardio", "rounded_hour"=>"06"},
{"average_attendance"=>0.154e3, "sum_attendance"=>154, "place_type"=>"cardio", "rounded_hour"=>"09"},
{"average_attendance"=>0.353e3, "sum_attendance"=>1059, "place_type"=>"cardio", "rounded_hour"=>"10"},
{"average_attendance"=>0.3e2, "sum_attendance"=>90, "place_type"=>"cardio", "rounded_hour"=>"11"},
{"average_attendance"=>0.45e2, "sum_attendance"=>90, "place_type"=>"swimming", "rounded_hour"=>"10"},
{"average_attendance"=>0.5e2, "sum_attendance"=>50, "place_type"=>"swimming", "rounded_hour"=>"11"}]

是否可以减少并对其进行分组以构建[sum_attendance,rounded_hour]数组?

3 个答案:

答案 0 :(得分:2)

> attendance_array.group_by{|e| e["place_type"]}.map{|k,v| {"name": k, "data": v.map{|r| [r["sum_attendance"],r["rounded_hour"]]}}}
# [
#   {
#       :name=>"cardio", 
#       :data=>[[999, "06"], [154, "09"], [1059, "10"], [90, "11"]]
#   }, 
#   {
#       :name=>"swimming", 
#       :data=>[[90, "10"], [50, "11"]]
#   }
# ]

首先group "place_type"然后将"name"作为组key"data"作为[sum_attendance, rounded_hour] <的数组准备哈希/ p>

答案 1 :(得分:1)

arr.each_with_object({}) do |g,h|
  k = g["place_type"]
  (h[k] ||= []) << ["#{g["rounded_hour"]}:00", g["sum_attendance"]]
end.map { |k,v| { name: k, data: v } }
  #=> [{:name=>"cardio", :data=>[["06:00", 999], ["09:00", 154],
  #                              ["10:00", 1059], ["11:00", 90]]},
  #    {:name=>"swimming", :data=>[["10:00", 90], ["11:00", 50]]}]

这可以写成如下。

arr.each_with_object(Hash.new { |h,k| h[k]=[] }) { |g,h|
  h[g["place_type"]] << ["#{g["rounded_hour"]}:00", g["sum_attendance"]] }.
    map { |k,v| { name: k, data: v } }

根据我的经验,第一种方法往往会更快一些。

在第二种方法

h = Hash.new { |h,k| h[k]=[] }

创建一个空哈希,以便在h[k]没有密钥h时调用k时执行该块。最初,哈希h为空,因此对于任何k,执行h[k]设置h[k]等于空数组。如果我们有

h[k] << 1

这导致

h[k] = h[k] << 1
  #=> [] << 1
  #=> [1]

如果以后我们有(对于相同的k

h[k] << 2

我们获得

h[k] = h[k] << 2
  #=> [1] << 2
  #=> [1,2]

这次不会调用该块,因为h现在有一个键k。更准确地说,方法Hash#[]在其参数不是其接收者的密钥h时调用该块。等式左边的h[k]是方法Hash#[]=,这就是为什么它也不会调用块。

答案 2 :(得分:0)

您可以使用以下内容:

arr.each_with_object(Hash.new { |k, v| k[v] = {name: v, data: []} }) do |res, exp|
  exp[res["place_type"]][:data] << ["#{res["rounded_hour"]}:00", res["sum_attendance"]]
end.values

# [
#   {:name => "cardio", :data => [["06:00", 999], ["09:00", 154], ["10:00", 1059], ["11:00", 90]]},
#   {:name => "swimming", :data => [["10:00", 90], ["11:00", 50]]}
# ]