2013-08-24 38 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所需的格式。 –