2017-08-31 55 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倍。但是,當然,您可以使用任何適合您的理解和可用性的方法。

相關問題