/ /ハッシュのRuby配列、2つのキーを比較し、別のキー/値の合計-ruby、arrays、hash

Rubyのハッシュ配列。2つのキーを比較し、別のキー/値を合計する - ルビ、配列、ハッシュ

Rubyには、次のハッシュの配列があります。

[
{: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 空です("")、それらのうちの1つのみを返します。したがって、上記の例を拡張するには、次のようにします。

[
{: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番目の例でミスを犯しました...それはoを持っているべきではありません。

回答:

回答№1は8

を使って開始 group_by 必要なキーを使用して、 reduce その qtys各値を1つのハッシュにするか、代わりに nil それらがすべての場合 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 2番目のサンプル入力データです。


回答№2の場合は3

あなたが欲しい」 enumberable.group_by

これはあなたが始めるはずです

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"}
]
}

回答№3の場合は-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}]

取る @アンドリューマーシャル 検討中の

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}]