【问题标题】:Ruby Array of Hashes - For each financial yearRuby Hash 数组 - 每个财政年度
【发布时间】:2017-01-11 05:50:29
【问题描述】:

我有一个交易数组,其中包含交易哈希。我想遍历交易哈希数组,并为每个财政年度求和利息和本金值。然后需要将这些添加到相应的数组中,按财政年度分组,如下所示。

简而言之:

每个财政年度:

1.对兴趣键的值求和

2.创建哈希

3.将哈希添加到各自的数组中

4.重复主值

我在第一步有点卡住:对于每个财政年度,做 x - 任何帮助将不胜感激。

Ruby 2.3.1

给定

 @transactions = [
  {"interest" => "120.00", "principal" => "250", "financial_year" => "2017"},
  {"interest" => "120.00", "principal" => "250", "financial_year" => "2017"},
  {"interest" => "120.00", "principal" => "250", "financial_year" => "2017"},
  {"interest" => "120.00", "principal" => "250", "financial_year" => "2018"},
  {"interest" => "120.00", "principal" => "250", "financial_year" => "2018"},
  {"interest" => "120.00", "principal" => "250", "financial_year" => "2019"},
  {"interest" => "120.00", "principal" => "250", "financial_year" => "2019"}
 ]

我想计算

 @interest_totals = [
    {"financial_year" => "2017", "total" => "360"}
    {"financial_year" => "2018", "total" => "240"}
    {"financial_year" => "2019", "total" => "240"}
 ]

 @principal_totals = [
    {"financial_year" => "2017", "total" => "750"}
    {"financial_year" => "2018", "total" => "500"}
    {"financial_year" => "2019", "total" => "500"}
 ]

【问题讨论】:

  • 虽然您的印刷引号看起来很漂亮,但您必须在 Ruby 中使用 "..."'...' 而不是 “...”‘...’
  • 我编辑了问题以纠正@Stefan 发现的错误。詹姆斯,请始终运行您的代码(例如在 IRB 中)以确保在发布之前它是正确的。
  • 会做@CarySwoveland - 谢谢

标签: ruby-on-rails arrays ruby hash


【解决方案1】:

使用injectreduceeach_with_object。我在下面使用了each_with_object,这样我就可以在一次迭代中计算两者的总和

interests, principals = @transactions.each_with_object([Hash.new(0), Hash.new(0)]) do |transaction, (interests, principals)|
  interests[transaction['financial_year']] += transaction['interest'].to_d
  principals[transaction['financial_year']] += transaction['principal'].to_d
end

p interests
# {"2017"=>#<BigDecimal:7fd1c6cc20f0,'0.36E3',9(18)>, "2018"=>#<BigDecimal:7fd1c6cc1d30,'0.24E3',9(18)>, "2019"=>#<BigDecimal:7fd1c6cc1970,'0.24E3',9(18)>}

p principals
# {"2017"=>#<BigDecimal:7fd1c6cc2050,'0.75E3',9(18)>, "2018"=>#<BigDecimal:7fd1c6cc1c90,'0.5E3',9(18)>, "2019"=>#<BigDecimal:7fd1c6cc18d0,'0.5E3',9(18)>}

这将为您提供一个哈希值,其中年份是键,值是总数。如果你真的需要一个哈希数组,使用zip

@interest_sum = interests.map do |interest|
  Hash[['financial_year', 'total'].zip(interest)]
end

【讨论】:

    【解决方案2】:

    您可以按年份对数值进行分组,然后将本金和利息金额相加

    @interest_totals =  @transactions.group_by{|a| a["financial_year"]}.map{|k, v| {"financial_year" => k, "total" => v.map{|e|e["interest"].to_i}.sum}}
    
    #=> [{ "financial_year" => "2017", "total" => 360 },
    #=>  { "financial_year" => "2018", "total" => 240 },
    #=>  { "financial_year" => "2019", "total" => 240 }]
    
    @principal_totals = @transactions.group_by{|a| a["financial_year"]}.map{|k, v| {"financial_year" => k, "total" => v.map{|e|e["principal"].to_i}.sum}}
    
    #=> [{ "financial_year" => "2017", "total" => 750 },
    #=>  { "financial_year" => "2018", "total" => 500 },
    #=>  { "financial_year" => "2019", "total" => 500 }]
    

    【讨论】:

      【解决方案3】:

      我建议你先计算下面的哈希。

      h = @transactions.each_with_object({}) do |g,h|
        h.update(g["financial_year"]=>g.reject { |k,_| k=="financial_year" }) do |_,o,n|
          o.merge(n) { |_,oo,nn| (oo.to_i + nn.to_i).to_s }
        end
      end
        #=> {"2017"=>{"interest"=>"360", "principal"=>"750"},
        #    "2018"=>{"interest"=>"240", "principal"=>"500"},
        #    "2019"=>{"interest"=>"240", "principal"=>"500"}}
      

      这使用Hash#update(又名merge!)和Hash#merge 的形式,它们使用一个块来确定在被合并的两个散列中存在的键的值。有关详细信息,请参阅文档,尤其是块变量的值,_onkoonn。 (在第一个块中,我使用下划线作为公共键来表示它不用于块计算。)

      这种中间解决方案的一个优点是,如果添加(例如“余额”)、删除或重命名键(“financial_year”除外),则无需更改它。

      您现在可以轻松地构造其他对象。例如,

      @interest_totals = h.map { |year,v| {"financial_year"=>year, "total"=> v["interest"] } }
        #=> [{"financial_year"=>"2017", "total"=>"360"},
        #    {"financial_year"=>"2018", "total"=>"240"},
        #    {"financial_year"=>"2019", "total"=>"240"}]   
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-20
        • 1970-01-01
        • 2012-06-02
        • 1970-01-01
        相关资源
        最近更新 更多