如何对具有相同类型的数组中相同键的值求和?

时间:2019-04-25 10:18:04

标签: ruby-on-rails arrays ruby sum

我有一个数组 input

[
  { type: 1, price: 50, discounted_price: 40 }, 
  { type: 2, price: 150, discounted_price: 140 },
  { type: 1, price: 40, discounted_price: 30 },
  { type: 2, price: 140, discounted_price: 130 }
]

以及预期的输出是什么

[
  { 
     type: 1, 
     price: 90, # =>  50 + 40
     discounted_price: 70 # =>  40 + 30
  },
  {
     type: 2,
     price: 290, # => 150 + 140
     discounted_price: 270 # => 140 + 130
  }
]

我已经尝试过reducegroup_by方法,但无法理解。

https://medium.com/@james.a.hughes/using-the-reduce-method-in-ruby-907f3c18ae1f

input.group_by { |item| 
  [item[:type]] 
}.values.flat_map { |items| 
  items.first.merge(price: items.sum { |h| h[:price].to_f }) 
}

它是价格的总和,但是我要价格和折扣价。

2 个答案:

答案 0 :(得分:2)

您可以使用group_byreduce

input.group_by { |item| item[:type] }.map do |_, collection|
  collection.reduce do |result, item| 
    result[:price] += item[:price]
    result[:discounted_price] += item[:discounted_price]
    result
  end
end

但是仅使用reduce也足够:

input.reduce([]) do |result, item|
  result_i = result.find { |result_i| result_i[:type] == item[:type] }

  if result_i
    result_i[:price] += item[:price]
    result_i[:discounted_price] += item[:discounted_price]
    result
  else
    result << item 
  end
end

答案 1 :(得分:2)

arr = [
  { type: 1, price:  50, discounted_price:  40 }, 
  { type: 2, price: 150, discounted_price: 140 },
  { type: 1, price:  40, discounted_price:  30 },
  { type: 2, price: 140, discounted_price: 130 }
]

arr.each_with_object({}) do |g,h|
  h.update(g[:type]=>g) do |_,o,n|
    { type: o[:type], price: o[:price]+n[:price],
      discounted_price: o[:discounted_price] + n[:discounted_price] }
  end
end.values
  #=> [{:type=>1, :price=>90,  :discounted_price=>70},
  #    {:type=>2, :price=>290, :discounted_price=>270}] 

请注意,values的接收者是

{1=>{:type=>1, :price=> 90, :discounted_price=> 70},
 2=>{:type=>2, :price=>290, :discounted_price=>270}} 

这使用Hash#update(也称为merge!)形式,并使用了该块

do |_,o,n|
  { type: o[:type], price: o[:price]+n[:price],
    discounted_price: o[:discounted_price] + n[:discounted_price] }
end

确定合并的两个哈希中存在的键的值。有关三个块变量_on的定义,请参见文档。

通常的做法是对未在块计算中使用的任何块变量使用下划线,主要是为了通知读者。在这里,第一个块变量保存公用密钥。 (某些人可能将_k用于该块变量。)

Hash#updateEnumerable#group_by在某种意义上紧密相关,因为(如此处)可以使用一个,而另一个可以使用。两者之间的选择通常是一种风格偏好。