A production has_many :p roduction_lines, production_line belongs_to :项, 项目has_one:食谱, 食谱has_many:recipe_lines, recipe_line belongs_to :项,
production_line
和recipe line
具有属性quantity
。我需要按项目对生产recipe_lines进行分组,数量等于 production_line.数量 * recipe_line.数量
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
}
其中键是item_id,值是数量。值正确。
但是我想回来:
item_quantities = [
{
id: 1,
name: "Tomato",
quantity: 10,
},
{
id: 2,
name: "Carrot",
quantity: 5
}
]
我应该如何更改我的解决方案来实现这一点?
首先,您的嵌套map
后跟flatten(1)
可以通过将第一个map
变成flat_map
来简化。如果这样做,则可以删除flatten(1)
。
从这一点开始,您的代码大部分时间都已完成,但您可以进行以下更改以获得所需的输出:
-
您可以按多个属性、名称和 ID 进行分组。在另一种语言中,你可以为此使用元组。Ruby 没有元组,所以我们可以使用 len-2 数组:
.group_by { |p| [p[:item_id], p[:item_name]] } .transform_values { |vals| vals.sum { |val| val[:quantity] } }
-
此时,您有一个哈希映射 [id,name] 元组到数量:
{ [1,"foo"] => 123, [2, "bar"] => 456 }
您可以使用
reduce
(或each_with_object
,如果您愿意,可以将其强制转换为所需的数据类型:.reduce([]) do |memo, ((id, name), quantity)| memo << { id: id, name: name, quantity: quantity } end
长相怪异的((id, name), quantity)
是一种解构。具体 https://jsarbada.wordpress.com/2019/02/05/destructuring-with-ruby/请参阅"解构块参数"和"解构哈希"部分。