2014-11-08 41 views
0

我想計算我的統計數據的增量。我已經試過HashDiff寶石來比較哈希。如何計算兩個哈希之間的增量?

a = {"Lima, Peru"=>"83", "Chicago, IL"=>"35"} 
b = {"Lima, Peru"=>"80", "Chicago, IL"=>"40", "Krakow, Poland" => '3'} 

CalculateDelta.new(A,B).execute

b = {"Lima, Peru"=>"-3", "Chicago, IL"=>"5", "Krakow, Poland" => '3'} 

甚至更​​好

b = {"Lima, Peru"=>["-", "3"], "Chicago, IL"=>["+", "5"], "Krakow, Poland" => ["+", '3']} 

我已經寫這樣的事情

class CalculateDeltas < Struct.new(:a, :b) 
    def calculate 
    aa = a.to_a 
    ba = b.to_a 
    c = aa + ba 
    c.group_by(&:first).map{|k,v| [k, v.map(&:last).inject(:+)]} 
    end 
end 

回答

2

像這樣的東西?:

class CalculateDelta 
    attr_reader :source, :target 
    def initialize(source, target) 
    @source = source 
    @target = target 
    end 

    def execute 
    target.each_with_object({}) do |(k, v), result| 
     result[k] = if source[k] 
     source_value, v = source[k].to_i, v.to_i 
     source_value > v ? ['-', "#{source_value - v}"]: ['+', "#{v - source_value}"] 
     else 
     ['+', v] 
     end 
    end 
    end 
end 

a = {"Lima, Peru"=>"83", "Chicago, IL"=>"35"} 
b = {"Lima, Peru"=>"80", "Chicago, IL"=>"40", "Krakow, Poland" => '3'} 

puts CalculateDelta.new(a,b).execute 
#=> {"Lima, Peru"=>["-", "3"], "Chicago, IL"=>["+", "5"], "Krakow, Poland"=>["+", "3"]} 
+0

哦!你是_Surya_ .. :-)爲什麼沒有名字..? :) – 2014-11-08 11:52:48

+0

爲什麼?發生了什麼..帳戶鎖定..? ;) – 2014-11-08 11:53:45

+0

是啊o.O告訴過你,對。錯誤:) – Surya 2014-11-08 11:54:12

0

Hash.new().tap{|h| b.each{|k,v| h[k] = v.to_i}; a.each{|k,v| h[k] -= v.to_i}}

返回{"Lima, Peru"=>-3, "Chicago, IL"=>5, "Krakow, Poland"=>3}


編輯 爲了使這個代碼僅返回哈希使用字符串:

Hash.new().tap{|h| b.each{|k,v| h[k] = v.to_i}; a.each{|k,v| h[k] -= v.to_i}}. 
    tap{|h| h.each{|k,v| h[k] = h[k].to_s }} 

返回{"Lima, Peru"=>"-3", "Chicago, IL"=>"5", "Krakow, Poland"=>"3"}

+0

'Hash.new()。tap {| h | b.each {| K,V | h [k] = v.to_i}; a.each {| K,V | NameError:未定義的局部變量或方法'b'for main:Object'無論如何,這並不會產生所需的輸出。值應該是string而不是fixnum。 – Surya 2014-11-08 11:50:22

+0

那麼哈希'a'和'b'必須在使用它們的範圍內......這就是你的錯誤告訴你的。爲了使字符串脫離它:'.tap {| h | h.each {| K,V | h [k] = h [k] .to_s}}' – lSoleyl 2014-11-08 11:54:16

1

保持簡單:

b.keys.each { |k| b[k] = (b[k].to_i-a[k].to_i).to_s if a.key?(k) } 
b #=> {"Lima, Peru"=>"-3", "Chicago, IL"=>"5", "Krakow, Poland" => "3"} 

注意,該規範是突變b

進一步簡化是可能的,但我不會建議吧:

b.keys.each { |k| b[k] = (b[k].to_i-a[k].to_i).to_s } 
b 

我聽到有人反對說a[k] = nil如果a沒有關鍵k。這是真的,但是nil.to_i => 0。 :-)