轨道对对象数组进行分组和求和



A production has_many :p roduction_lines, production_line belongs_to :项, 项目has_one:食谱, 食谱has_many:recipe_lines, recipe_line belongs_to :项,

production_linerecipe 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)

从这一点开始,您的代码大部分时间都已完成,但您可以进行以下更改以获得所需的输出:

  1. 您可以按多个属性、名称和 ID 进行分组。在另一种语言中,你可以为此使用元组。Ruby 没有元组,所以我们可以使用 len-2 数组:

    .group_by { |p| [p[:item_id], p[:item_name]] }
    .transform_values { |vals| vals.sum { |val| val[:quantity] } }
    
  2. 此时,您有一个哈希映射 [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/请参阅"解构块参数"和"解构哈希"部分。

最新更新