将对象排序为类型的哈希

时间:2018-07-04 14:31:34

标签: arrays ruby hash

我想遍历一组对象并将它们分类为产品类型哈希。

我要寻找的结果是这样的。

{ "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>>]

1 个答案:

答案 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正是出于这一确切目的-使用此方法将提供针对当前任务进行了优化的可读方法。

希望能有所帮助-如果您有任何疑问,请告诉我您的情况:)