生产has_many:production_lines, production_line所属项:项目, has_one项:配方, 配方has_many:recipe_lines, recipe_line归属于:item,
production_line
and recipe line
have attribute quantity
. I need to group recipe_lines for a production by item, with quantity that equals to production_line.quantity * recipe_line.quantity
def item_quantities
array = production_lines.map do |p|
p.item.recipe.recipe_lines.map do |r|
{
item_id: r.item_id,
item_name: r.item.name,
quantity: r.quantity * p.quantity
}
end
end
array.flatten(1).group_by { |p| p[:item_id] }
.transform_values { |vals| vals.sum { |val| val[:quantity] } }
end
返回:
item_quantities = {
1: 10,
2: 5
}
其中key是item_id,value是数量。值是正确的。
但是我想返回:
item_quantities = [
{
id: 1,
name: "Tomato",
quantity: 10,
},
{
id: 2,
name: "Carrot",
quantity: 5
}
]
我应该如何更改解决方案以实现该目标?
First of all, your nested
map
followed byflatten(1)
can be simplified by making the firstmap
intoflat_map
. If you do this you could remove theflatten(1)
.从这一点开始,您的代码已遍历整个过程,但是您可以进行以下更改以获得所需的输出:
you can group by multiple attributes, name and id. In another language you might use a tuple for this. Ruby doesn't have tuples, so we can just use a len-2 array:
At this point you have a hash mapping [id,name] tuple to quantity:
and you can coerce this to the desired data type using
reduce
(oreach_with_object
, if you prefer):The wierd looking
((id, name), quantity)
is a kind of destructuring. See https://jsarbada.wordpress.com/2019/02/05/destructuring-with-ruby/ specifically the sections on "Destructuring Block Arguments" and "Destructuring Hashes".