2014-02-26 52 views
1

我有薪金的對象,如數組:聚合上枚舉紅寶石

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 

我應該怎麼做?

回答

2
class Salary 
    attr_reader :person, :job, :salary 

    def initialize(args={}) 
    @person = args[:person] 
    @job = args[:job] 
    @salary = args[:salary] 
    end 

    def inspect 
    "<Person #{person}, Job #{job}, #{salary}>" 
    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})] 
# => [<Person 1, Job 1, 400>, <Person 1, Job 1, 300>, 
#  <Person 1, Job 1, 300>, <Person 1, Job 2, 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 
# => [<Person 1, Job 1, 1000>, <Person 1, Job 2, 500>] 
+0

謝謝!爲了方便添加新的屬性,我修改了'map'塊: 'end.values.map do | group |' 'person = group [0]' 'person.salary =(group.map&薪水).reduce:+' 'person' 'end' –

1

你的數組包含一個類的實例。鑑於這個類,@Rafa已經回答了你的問題。你可能對班上有控制權,但是假設你沒有?假設你傳遞了該數組而其他人維護了這個類。我不確定這是否是好的做法,但這是我想要解決的情況。

此外,假設您只是想確定每個:person/:job pair的總工資(而不是創建具有期望值的實例變量的類的實例)。您的陣列可能如下所示:

p salaries 
    #=> #<Salary:0x000001010cb230 @person=1, @job=1, @salary=400>, 
    #=> #<Salary:0x000001010cb1e0 @person=1, @job=1, @salary=300>, 
    #=> #<Salary:0x000001010cb190 @person=1, @job=1, @salary=300>, 
    #=> #<Salary:0x000001010cb140 @person=1, @job=2, @salary=500>] 

很明顯,Salary類具有所需的三個實例變量。 (我生成此使用@拉法的類定義,但沒有attr_readerinspect。)

Salaries.instance_methods(false) #=> [] 

告訴我們,對這些實例變量沒有干將。但是,我們可以使用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}]