2013-08-24 75 views
2

在Ruby中,我有以下哈希值的數組:紅寶石陣列,比較2個鍵和總結其他鍵/值

[ 
    {:qty => 1, :unit => 'oz', :type => 'mass'}, 
    {:qty => 5, :unit => 'oz', :type => 'vol'}, 
    {:qty => 4, :unit => 'oz', :type => 'mass'}, 
    {:qty => 1, :unit => 'lbs', :type => 'mass'} 
] 

我需要能夠做的是比較由:unit的元素和:type,然後在它們相同時總計:qty。將所得的陣列應該像如下:

[ 
    {:qty => 5, :unit => 'oz', :type => 'mass'}, 
    {:qty => 5, :unit => 'oz', :type => 'vol'}, 
    {:qty => 1, :unit => 'lbs', :type => 'mass'} 
] 

如果陣列具有多個散列,其中:qtynil:unit爲空(""),那麼這將只返回其中的一個。因此,要延長上面的例子,這樣的:

[ 
    {:qty => 1, :unit => 'oz', :type => 'mass'}, 
    {:qty => nil, :unit => '', :type => 'Foo'}, 
    {:qty => 5, :unit => 'oz', :type => 'vol'}, 
    {:qty => 4, :unit => 'oz', :type => 'mass'}, 
    {:qty => 1, :unit => 'lbs', :type => 'mass'}, 
    {:qty => nil, :unit => '', :type => 'Foo'} 
] 

會變成這樣:

[ 
    {:qty => 5, :unit => 'oz', :type => 'mass'}, 
    {:qty => nil, :unit => '', :type => 'Foo'}, 
    {:qty => 5, :unit => 'oz', :type => 'vol'}, 
    {:qty => 1, :unit => 'lbs', :type => 'mass'} 
] 

編輯:對不起,在第二個例子中犯了一個錯誤......它不應該有鄰。

+2

你打算怎麼給加分? – sawa

+1

你的第二個例子沒有意義,爲什麼在結果中沒有單位「o」的散列? –

+0

你說得對,只是編輯它。 –

回答

8

開始將每個值轉換爲單個散列值,或者使用nil(如果它們都是):

properties.group_by do |property| 
    property.values_at :type, :unit 
end.map do |(type, unit), properties| 
    quantities = properties.map { |p| p[:qty] } 
    qty = quantities.all? ? quantities.reduce(:+) : nil 
    { type: type, unit: unit, qty: qty } 
end 

#=> [{:type=>"mass", :unit=>"oz", :qty=>5}, 
# {:type=>"Foo", :unit=>"", :qty=>nil}, 
# {:type=>"vol", :unit=>"oz", :qty=>5}, 
# {:type=>"mass", :unit=>"lbs", :qty=>1}] 

其中properties是您的第二個樣本輸入數據。

+0

'reduce(:+)'=>'sum(0)'(如果您使用的是有效支持) –

+1

@MarianTheisen Ruby沒有'sum'方法。 – naomik

+1

@MarianTheisen Ruby沒有'sum'方法,它只存在於ActiveSupport中。 –

3

你會想enumberable.group_by

這應該讓你使用group_by你想要的鍵,然後reduceqty開始吧

items.group_by { |item| item.values_at(:unit, :type) } 

輸出

{ 
    ["oz", "mass"]=> [ 
    {:qty=>1, :unit=>"oz", :type=>"mass"}, 
    {:qty=>4, :unit=>"oz", :type=>"mass"} 
    ], 
    ["oz", "vol"]=>[ 
    {:qty=>5, :unit=>"oz", :type=>"vol"} 
    ], 
    ["lbs", "mass"]=>[ 
    {:qty=>1, :unit=>"lbs", :type=>"mass"} 
    ] 
} 
-1
ar = [{:qty => 1, :unit => 'oz', :type => 'mass'}, {:qty => nil, :unit => '', :type => 'Foo'}, 
     {:qty => 5, :unit => 'oz', :type => 'vol'}, 
     {:qty => 4, :unit => 'oz', :type => 'mass'}, {:qty => 1, :unit => 'lbs', :type => 'mass'}, 
     {:qty => nil, :unit => 'o', :type => 'Foo'}] 

result = ar.each_with_object(Hash.new(0)) do |e,hsh| 
    if hsh.has_key?({:unit => e[:unit], :type => e[:type]}) 
     hsh[{:unit => e[:unit], :type => e[:type]}] += e[:qty] 
    else 
     hsh[{:unit => e[:unit], :type => e[:type]}] = e[:qty] 
    end 
end 

result.map{|k,v| k[:qty] = v;k }.delete_if{|h| h[:qty].nil? and !h[:unit].empty? } 
# => [{:unit=>"oz", :type=>"mass", :qty=>5}, 
#  {:unit=>"", :type=>"Foo", :qty=>nil}, 
#  {:unit=>"oz", :type=>"vol", :qty=>5}, 
#  {:unit=>"lbs", :type=>"mass", :qty=>1}] 

@Andrew馬歇爾考慮

ar = [{:qty => 1, :unit => 'oz', :type => 'mass'}, {:qty => nil, :unit => '', :type => 'Foo'}, 
     {:qty => 5, :unit => 'oz', :type => 'vol'}, 
     {:qty => 4, :unit => 'oz', :type => 'mass'}, {:qty => 1, :unit => 'lbs', :type => 'mass'}, 
     {:qty => nil, :unit => 'o', :type => 'Foo'}] 

result = ar.each_with_object(Hash.new(0)) do |e,hsh| 
    if hsh.has_key?({:unit => e[:unit], :type => e[:type]}) 
     hsh[{:unit => e[:unit], :type => e[:type]}] += e[:qty] 
    else 
     hsh[{:unit => e[:unit], :type => e[:type]}] = e[:qty] 
    end 
end 

result.map{|k,v| k[:qty] = v;k }.delete_if{|h| h[:qty].nil? and h[:unit].empty? } 
# => [{:unit=>"oz", :type=>"mass", :qty=>5}, 
#  {:unit=>"oz", :type=>"vol", :qty=>5}, 
#  {:unit=>"lbs", :type=>"mass", :qty=>1}, 
#  {:unit=>"o", :type=>"Foo", :qty=>nil}] 
+0

你說你的代碼給出的結果不是實際結果。 –

+0

是的,它是..見行*如果數組有多個散列,其中:qty爲零且單位爲空(「」),那麼它只會返回其中的一個。*。 –

+0

不,我的意思是,你在答案結尾的結果不是你的代碼實際返回的結果。並不是OP所需的格式。 –