2015-01-09 54 views
0

我有散列的一個這樣的數組:清理哈希數組中多個值的方法?

data = [ 
{group: "A", result: 1}, 
{group: "B", result: 1}, 
{group: "A", result: 0}, 
{group: "A", result: 1}, 
{group: "B", result: 1}, 
{group: "B", result: 1}, 
{group: "B", result: 0}, 
{group: "B", result: 0} 
] 

集團將僅是A或B,並且結果將僅是1或0。我要計數的結果多少次是0或1爲每個組,即得到了提示,像這樣:

A: result is "1" 2 times 
    result is "0" 1 time 
B: result is "1" 3 times 
    result is "0" 2 times 

我想存儲的實際效果在嵌套散列,像:

{ a: { pass: 2, fail: 1 }, b: { pass: 3, fail: 2 } } 

但這可能不是BES不管怎樣,所以我在這裏接受其他想法。

什麼是最簡潔的方式來做到這一點在Ruby中,而只有一次數據迭代?以某種方式使用data.injectdata.count

回答

3
stats = Hash[data.group_by{|h| [h[:group], h[:result]] }.map{|k,v| [k, v.count] }] 
#=> {["A", 1]=>2, ["B", 1]=>3, ["A", 0]=>1, ["B", 0]=>2} 

我會留下改造所需的格式給你;-)

0

這樣會超過哈希只有一次:

result = Hash.new { |h, k| h[k] = { pass: 0, fail: 0 }} 
data.each do |item| 
    result[item[:group]][item[:result] == 0 ? :fail : :pass] += 1 
end 
result 
# => {"A"=>{:pass=>2, :fail=>1}, "B"=>{:pass=>3, :fail=>2}} 
0

如果這是你的忠實地所需的輸出則像這樣的工作:

def pass_fail_hash(a=[],statuses=[:pass,:fail]) 
    a.map(&:dup).group_by{|h| h.shift.pop.downcase.to_sym}.each_with_object({}) do |(k,v),obj| 
    obj[k] = Hash[statuses.zip(v.group_by{|v| v[:result]}.map{|k,v| v.count})] 
    statuses.each {|status| obj[k][status] ||= 0 } 
    end 
end 

然後

pass_fail_hash data 
#=> {:a=>{:pass=>2, :fail=>1}, :b=>{:pass=>3, :fail=>2}} 

感謝@CarySwoveland指出我的原始方法沒有考慮沒有通過或失敗值的情況。現在已經解決了這個問題,所以像[{ group: "A", result: 1 }]這樣的散列數組現在將顯示{a:{:pass => 1, :fail => 0}},它以前的地址是{a:{:pass => 1, :fail => nil}}

+0

我覺得是需要一個小的調整:對'data = [{group:「A」,result:1}]','pass_fail_hash data#=> {:a => {:pass => 1,:fail => nil}}'。 – 2015-01-10 02:44:49

+0

@CarySwoveland謝謝你指出這一點。現在我已經解決了這個問題,所以'nil'值恰當地爲'0'。 – engineersmnky 2015-01-12 16:35:17

0

你可以使用的Hash#update,需要一個塊的形式(同Hash#merge!),以確定被合併包含在這兩個哈希鍵的值:

data.map(&:values).each_with_object({}) { |(g,r),h| 
    h.update({g.to_sym=>{pass: r, fail: 1-r } }) { |_,oh,nh| 
    { pass: oh[:pass]+nh[:pass], fail: oh[:fail]+nh[:fail] } } } 
    #=> {:A=>{:pass=>2, :fail=>1}, :B=>{:pass=>3, :fail=>2}}