我想遍历一组对象并将它们分类为产品类型哈希。
我要寻找的结果是这样的。
{ "Bike" => [line_item, line_item, line_item], "Car" => [line_item] }
到目前为止,我有以下内容
PRODUCT_TYPES = Hash.new []
Input.cart.line_items.each do |item|
PRODUCT_TYPES[item.variant.product.product_type] << line_item
end
实现此目标的正确方法是什么?
编辑:
这是我的输入内容
[#<LineItem:0x7f5994288da0 @grams=0, @original_line_price=#<Money:0x7f5994289220>, @discounts=[],
@properties_was={}, @line_price=#<Money:0x7f5994289370>, @variant=#<Variant:0x7f59942898b0>, @properties={},
@adjustments=[], @quantity=1, @source_indices={"12593518772283:86c53a47791a6f36173f4ecc3039ec9b"=>1},
@line_price_was=#<Money:0x7f5994289370>>]
答案 0 :(得分:1)
最简单的方法是使用group_by
:
Input.cart.line_items.group_by { |item| item.variant.product.product_type }
这应该完全按要求返回哈希值-评估后的块的输出将作为哈希键(即item.variant.product.product_type
)返回,并将项作为值数组分配给这些键。
一个旁注-当您查询每个line_item
的相关记录中的一些记录时,including
值得避免N + 1个问题,例如
Input.cart.line_items.includes(variant: { product: :product_type }).group_by do |item|
item.variant.product.product_type
end
这是使用each_with_object
之后实现目标的另一种简单方法:
Input.cart.line_items.each_with_object(Hash.new { |h, k| h[k] = [] }) do |item, hash|
hash[item.variant.product.product_type] << item
end
编辑:只是意识到您的问题被标记为Ruby而不是Rails,在这种情况下each_with_object
不可用,尽管您可以使用reduce
实现类似的目的:
Input.cart.line_items.reduce(Hash.new { |h, k| h[k] = [] }) do |hash, item|
hash.tap { |h| h[item.variant.product.product_type] << item }
end
请注意tap
的使用:reduce
返回该块求值而不是对象的值,并分配给第一个块arg(在这种情况下为hash
)。使用tap
可确保始终是哈希。
就“正确”而言,group_by
正是出于这一确切目的-使用此方法将提供针对当前任务进行了优化的可读方法。
希望能有所帮助-如果您有任何疑问,请告诉我您的情况:)