2017-08-31 52 views
1

我有一个数组,它是结构这样的:集团在数组键,得到最大值和平均值

{"status": "ok", "data": [{"temp": 22, "wind": 351.0, "datetime": "20160815-0330"}, {"temp": 21, "wind": 321.0, "datetime": "20160815-0345"}]} 

我期待组由datetime键(忽略时间),发现最大temp和平均wind

我试过的东西如下,但不确定该怎么办max_by平均在同一地图:

@data['data'].group_by { |d| d.values_at("datetime") }.map { |_, v| v.max_by { |h| h["temp"] } } 

回答

1

所以,当你做"data": { ... },该data实际上变成一个符号,而不是字符串所以你需要做的是这样的:由:datetime关键

@data[:data].group_by { |data| data[:datetime].split('-')[0] } 

以组,忽略时间部分(我假设,时间部分是-后只是一切)。然后,你最终有一个哈希看起来像:

{"20160815"=>[{:temp=>22, :wind=>351.0, :datetime=>"20160815-0330"}, {:temp=>21, :wind=>321.0, :datetime=>"20160815-0345"}]} 

,并找到:wind的最大:temp平均可以这样做:

results = @data[:data].group_by { |data| data[:datetime].split('-')[0] }.map do |date, values| 
    [date, { 
    maximum_temp: values.max_by { |value| value[:temp] }[:temp], 
    average_wind: values.sum { |value| value[:wind] }.to_f/values.length 
    }] 
end.to_h 
# => {"20160815"=>{:maximum_temp=>22, :average_wind=>336.0}} 
+0

很好的解释简单的石灰。虽然我得到一个:未定义的方法'group_by'为零:NilClass,错误。 – DollarChills

+0

键应该是字符串还是符号?您提供的示例输入使用了符号,您尝试使用的代码示例使用了字符串。 –

+0

他们是字符串。将键从对象切换到字符串后,我已经从该错误中移除。 – DollarChills

0

上述方法工作得很好,代码似乎位通过利用max_by和访问值[:temp]然后求和和显式地to_h。所以,如果你考虑性能和良好的可读性明智的,你可以使用基本的每个像下面,

data = {"20160815"=>[{:temp=>22, :wind=>351.0, :datetime=>"20160815-0330"}, {:temp=>21, :wind=>321.0, :datetime=>"20160815-0345"}]} 
data.map do |k, v|                                          
    winds = []                                           
    temps = []                                           
    v.each do |item|                                          
    winds << item[:wind]                                         
    temps << item[:temp]                                        
    end                                             
    {k => {max_temp: temps.max, avg_wind: winds.inject(:+).to_f/winds.length}}                           
end 

和输出低于,

# => {"20160815"=>{:max_temp=>22, :avg_wind=>336.0}} 

下面是利用之间的小基准的每一个和max_by

data = {"20160815"=>[{:temp=>22, :wind=>351.0, :datetime=>"20160815-0330"}, {:temp=>21, :wind=>321.0, :datetime=>"20160815-0345"}]} 


def by_each(data) 
    data.map do |k, v| 
    winds = [] 
    temps = [] 
    v.each do |item| 
     winds << item[:wind] 
     temps << item[:temp] 
    end 
    {k => {max_temp: temps.max, avg_wind: winds.inject(:+).to_f/winds.length}} 
    end 
end 

def by_max(data) 
    data.map do |date, values| 
    [date, { 
     maximum_temp: values.max_by { |value| value[:temp] }[:temp], 
     average_wind: values.sum { |value| value[:wind] }.to_f/values.length 
    }] 
    end.to_h 
end 

Benchmark.ips do |x|                                         
    x.config(times: 10)                                         
    x.report 'BY_EACH' do                                         
    by_each(data)                                          
    end 
    x.report 'BY_MAX' do                                         
    by_max(data)                                          
    end                                             
    x.compare!                                           
end 

而基准O/p是像下面,

Warming up -------------------------------------- 
      BY_EACH 18.894k i/100ms 
       BY_MAX 13.793k i/100ms 
Calculating ------------------------------------- 
      BY_EACH 226.160k (± 5.3%) i/s -  1.134M in 5.025488s 
       BY_MAX 154.745k (± 5.8%) i/s - 772.408k in 5.006365s 

Comparison: 
      BY_EACH: 226159.5 i/s 
       BY_MAX: 154744.8 i/s - 1.46x slower 

因此,您可以看到BY_MAX比BY_EACH慢1.46倍。但是,当然,您可以使用任何适合您的理解和可用性的方法。

相关问题