可枚举的ruby上的聚合

我有一个Salary对象数组,例如:

Person 1, Job 1, 400 Person 1, Job 1, 300 Person 1, Job 1, 300 Person 1, Job 2, 500 

我想聚合它们并对数字求和,这样结果将是:

 Person 1, Job 1, 1000 Person 1, Job 2, 500 

我该怎么办呢?

 class Salary attr_reader :person, :job, :salary def initialize(args={}) @person = args[:person] @job = args[:job] @salary = args[:salary] end def inspect "" end end salaries = [ Salary.new({:person => 1, :job => 1, :salary => 400}), Salary.new({:person => 1, :job => 1, :salary => 300}), Salary.new({:person => 1, :job => 1, :salary => 300}), Salary.new({:person => 1, :job => 2, :salary => 500})] # => [, , # , ] grouped_salaries = salaries.group_by do |salary| [salary.person, salary.job] end.map do |key, value| Salary.new(person: key[0], job: key[1], salary: value.reduce(0) { |acc, s| acc + s.salary }) end # => [, ] 

您的数组包含类的实例。 鉴于该课程,@ Rafa已经回答了你的问题。 你可能已经掌控了class级,但是假设你没有? 假设您传递了该数组并且其他人维护了该类。 我不确定这是不是很好的做法,但这就是我想要解决的问题。

此外,假设您只想确定每个:person/:job pair的总薪水(而不是创建具有所需值的实例变量的类的实例)。 您的数组可能如下所示:

 p salaries #=> #, #=> #, #=> #, #=> #] 

显然,Salary类具有所需的三个实例变量。 (我使用attr_reader的类定义生成了这个,但没有attr_readerinspect 。)

 Salaries.instance_methods(false) #=> [] 

告诉我们这些实例变量没有getter。 但是,我们可以使用Object#instance_variable_get检索它们的值。 然后按人/工作对汇总工资是一件简单的事情:

 def aggregate_salaries(salaries) salaries .group_by { |e| [e.instance_variable_get(:@person), e.instance_variable_get(:@job)] } .map do |(person,job),ae| tot_sal = ae.reduce(0) { |t,e| t + e.instance_variable_get(:@salary) } {person: person, job: job, salary: tot_sal} end end aggregate_salaries(salaries) #=> [{:person=>1, :job=>1, :salary=>1000}, # {:person=>1, :job=>2, :salary=>500}]