Ruby哈希数组,比较两个键并求和另一个键/值
在Ruby中,我有以下哈希数组:Ruby哈希数组,比较两个键并求和另一个键/值,ruby,arrays,hash,Ruby,Arrays,Hash,在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'} ] 我需要能够
[
{: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'}
]
如果数组有多个哈希,其中:qty
为nil
,而: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'}
]
编辑:抱歉,在第二个示例中犯了一个错误。。。它不应该有你想要的o.
这应该让你开始
items.group_by { |item| item.values_at(:unit, :type) }
输出
{
[“盎司”,“质量”]=>[
{:数量=>1,:单位=>“oz”,:类型=>“质量”},
{:数量=>4,:单位=>“盎司”,“类型=>“质量”}
],
[“盎司”,“体积”]=>[
{:数量=>5,:单位=>oz,:类型=>vol}
],
[“磅”,“质量”]=>[
{:数量=>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
是第二个示例输入数据
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}]
你打算如何给加分?你的第二个例子没有意义,为什么结果中没有带单位
'o'
的散列?你是对的,只是编辑了它。你希望有很多这样的数据和工作要做吗?减少(:+)
=>求和(0)
(如果你使用的是activesupport)@Marianteisen Ruby没有sum
方法。@Marianteisen Ruby没有sum
方法,它只存在于ActiveSupport中。@AndrewMarshall但您错过了一个条目。。。那个奖金很重要……:):)@事实并非如此,OP的示例输出不符合其应如何生成的标准。见我对这个问题的评论。我的答案适用于类型和单位之间的任何“和”条件。是的,它是。。如果数组有多个散列,其中:qty为nil且单位为空(“”),那么它将只返回其中一个。不,我的意思是,您在答案末尾得到的结果不是代码实际返回的结果。这不是OP想要的格式。我知道我做了什么。我正在查看result
的值。此外,你没有遵循OP的标准。如果:unit
不为空,则删除该元素。