如何根据数组中对象的两个属性创建哈希?

时间:2017-01-02 14:43:52

标签: ruby sum

假设我有以下课程product.rb

require 'yaml'

class Product
    attr_accessor :id, :price

    def initialize args = {}
        options = {:id => "", :price => 0}.merge(args)
        self.id, self.price = options[:id], options[:price]
    end

    def inspect
        self.to_yaml        
    end
end

以下示例程序example.rb

require_relative 'product'

products = Array.new

(1..5).each do |n| # Create 5 products with random id and price
    products << Product.new(
        :id => rand(1..5),
        :price => rand(10..50))
end

products.each { |p| puts p.inspect }

运行example.rb的示例输出:

C:\>ruby example.rb
--- !ruby/object:Product
id: 3
price: 48
--- !ruby/object:Product
id: 2
price: 47
--- !ruby/object:Product
id: 5
price: 32
--- !ruby/object:Product
id: 5
price: 49
--- !ruby/object:Product
id: 3
price: 33

结果是一个Product类型的对象数组,带有重复的ID。

如何创建一个以id作为键的哈希值和作为值的价格总和?

期望结果的示例:

{ "2" => 47, "3" => 81, "5" => 81 } # { id => sum of price }

3 个答案:

答案 0 :(得分:4)

您可以使用each_with_object注入默认值为0的哈希值,如下所示:

products.each_with_object(Hash.new(0)) { |p, result| result[p.id] += p.price }

答案 1 :(得分:1)

products = Array.new
sum_hash = Hash.new(0) # new hash with default 0 value

(1..5).each do |n| # Create 5 products with random id and price
  id = rand(1..5)
  price = rand(10..50)

  sum_hash[id] += price

  products << Product.new(
    :id => id,
    :price => price)
end

products.each { |p| puts p.inspect }    

答案 2 :(得分:0)

另一种可能性是使用group_by

products.group_by(&:id)
        .map{|id, ps| [id, ps.map(&:price).inject(:+)] }
        .to_h