【问题标题】:Ruby - Array of Hashes - Find value from DateTime KeyRuby - 哈希数组 - 从 DateTime 键中查找值
【发布时间】:2025-11-25 21:50:01
【问题描述】:

我有一个哈希数组保存到数据库中。日期采用 DateTime 格式。

@item.yearly_interest_totals = [
    {"financial_year" => "Sun, 01 Jan 2017 00:00:00 +0000", "total" => "360"},
    {"financial_year" => "Mon, 01 Jan 2018 00:00:00 +0000", "total" => "240"},
    {"financial_year" => "Tue, 01 Jan 2019 00:00:00 +0000", "total" => "240"}
]

在我看来,我在一个可变的金融年度中有一个特定的财政年度

如何使用 Financial_year 键显示对应的值?我对将财政年度整数与 DateTime 对象进行比较有点困惑......

例如:

<tr>
         <td>Financial Year: <%= financial_year.to_i %></td>
         <td><%= @item.yearly_interest_totals.find{|i| i["financial_year"] == DateTime.new(financial_year.to_i,1,1)}["total"] %></td>
</tr>

这应该显示为:

财政年度:2017 360

仅供参考:Rails 5.0.0.1、Ruby 2.3.1、本地 Postgres 数据库

【问题讨论】:

    标签: ruby-on-rails arrays ruby datetime hash


    【解决方案1】:
    financial_year = 2018
    yearly_interest_totals.map do |t|
      t["total"] if Date.parse(t["financial_year"]).year == financial_year
    end.compact
    #⇒ ["240"]
    

    yearly_interest_totals.detect do |t|
      Date.parse(t["financial_year"]).year == financial_year 
    end["total"]
    #⇒ "240"
    

    【讨论】:

      【解决方案2】:

      假设:

      financial_year = 2017
      

      那么你可以这样做:

      @items.yearly_interest_totals.each do |yit|
        yit.merge!(DateTime.strptime(yit['financial_year'], "%a, %d %b %Y %H:%M:%S %z").year => yit['total'])
      end
      #=>[
      #   {"financial_year"=>"Sun, 01 Jan 2017 00:00:00 +0000", "total"=>"360", 2017=>"360"},
      #   {"financial_year"=>"Mon, 01 Jan 2018 00:00:00 +0000", "total"=>"240", 2018=>"240"},
      #   {"financial_year"=>"Tue, 01 Jan 2019 00:00:00 +0000", "total"=>"240", 2019=>"240"}
      # ]
      

      现在在你看来:

      <tr>
        <td>Financial Year: <%= financial_year %></td>
        <td><%= @item.yearly_interest_totals.find{|yit| yit[financial_year] }[financial_year] %></td>
      </tr>
      

      请注意,我假设您是在另一个财政年度循环中展示这一点,然后上述解决方案的时间复杂度为 O(n2),这不是一种有效的方法,否则它可以工作。


      如果我们可以将此数组更改为哈希的哈希值,那么它对于大型数据集的效果会更好:

      yearly_interest_totals = @items.yearly_interest_totals.each_with_object({}) do |yit, obj|
        obj[DateTime.strptime(yit['financial_year'], "%a, %d %b %Y %H:%M:%S %z").year] = yit
      end
      # =>
      # {
      #   2017=>{"financial_year"=>"Sun, 01 Jan 2017 00:00:00 +0000", "total"=>"360"}, 
      #   2018=>{"financial_year"=>"Mon, 01 Jan 2018 00:00:00 +0000", "total"=>"240"}, 
      #   2019=>{"financial_year"=>"Tue, 01 Jan 2019 00:00:00 +0000", "total"=>"240"}
      # }
      

      现在在你看来:

      <tr>
        <td>Financial Year: <%= financial_year %></td>
        <td><%= yearly_interest_totals[financial_year]['total'] %></td>
      </tr>
      

      如果您有多个一年的财务数据,那么我建议您将 yearly_interest_totals 哈希值作为数组或更新总数(无论哪个有效)。

      【讨论】: