【问题标题】:Rails: Retrieve keys and values from hashmapRails:从哈希图中检索键和值
【发布时间】:2022-01-31 11:42:04
【问题描述】:

我正在尝试为图表检索两个带有日期的单独值...

 @a = Applications.all.group_by_month(:created_at, format: '%b %y').count
 @b = Secondary_Applications.all.group_by_month(:created_at, format: '%b %y').count

我是这样映射的……

keys = [@a, @b].flat_map(&:keys).uniq

@ab_final = keys.map do |k| 
                {k => [{applications_one: @a[k] || 0}, 
                {applications_two: @b[k] || 0}]}
              end

这给了...

[
{"May 21"=>
  [{:applications_one=>20}, {:applications_two=>0}]},

{"Jun 21"=>
  [{:applications_one=>15}, {:applications_two=>0}]},

{"Jul 21"=>
  [{:applications_one=>8}, {:applications_two=>11}]},

 {"Aug 21"=>
  [{:applications_one=>1}, {:applications_two=>2}]} 
] 

我不知道如何从这一点获取值。您将如何提取日期键和值,例如...?

预期输出:

applications_one [20, 15, 8, 1]

applications_two [0, 0, 11, 2]

日期 [5 月 21 日、6 月 21 日、7 月 21 日、8 月 21 日]

ty

【问题讨论】:

  • 什么是输入,什么是预期输出?请编辑您的问题

标签: arrays ruby-on-rails hashmap


【解决方案1】:

这是你想要达到的目标吗?

arr = [
  {"May 21"=>
    [{:applications_one=>20}, {:applications_two=>0}]},

  {"Jun 21"=>
    [{:applications_one=>15}, {:applications_two=>0}]},

  {"Jul 21"=>
    [{:applications_one=>8}, {:applications_two=>11}]},

   {"Aug 21"=>
    [{:applications_one=>1}, {:applications_two=>2}]}
  ]

applications_one = []
applications_two = []
dates = []

arr.each do |hash|
  hash.values.flatten.each do |element|
    applications_one << element[:applications_one] if element.key?(:applications_one)
    applications_two << element[:applications_two] if element.key?(:applications_two)
  end
  dates << hash.keys.first
end

2.7.3 :027 > applications_one
 => [20, 15, 8, 1] 
2.7.3 :028 > applications_two
 => [0, 0, 11, 2] 
2.7.3 :029 > dates
 => ["May 21", "Jun 21", "Jul 21", "Aug 21"] 
2.7.3 :030 > 

【讨论】:

    【解决方案2】:

    我会做一些不同的事情。将从以这种方式构建数据开始:

    @ab_final = keys.map do |k| 
        {date: k, applications_one: @a[k] || 0, applications_two: @b[k] || 0}}
    end
    

    这应该给你:

    @ab_final = [
        {:date=>"May 21", :applications_one=>20, :applications_two=>0},
        {:date=>"Jun 21", :applications_one=>15, :applications_two=>0},
        {:date=>"Jul 21", :applications_one=>8, :applications_two=>11},
        {:date=>"Aug 21", :applications_one=>1, :applications_two=>2} 
    ]
    

    然后你会得到这样的预期输出:

    dates = @ab_final.map{|d| d[:date]}
    => ["May 21", "Jun 21", "Jul 21", "Aug 21"]
    
    applications_one = @ab_final.map{|d| d[:applications_one]}
    => [20, 15, 8, 1]
    
    applications_two = @ab_final.map{|d| d[:applications_two]}
    => [0, 0, 11, 2]
    

    【讨论】:

      【解决方案3】:

      我已将您的示例数组修改如下:

      arr = [
        {"May 21"=> [{:applications_one=> 20}, {:applications_two=>  0}]},
        {"Jun 21"=> [{:applications_two=>  0}, {:applications_one=> 15}]},
        {"Jul 21"=> [{:applications_one=>  6}, {:applications_three=>4}]},
        {"Aug 21"=> [{:applications_one=>  1}, {:applications_two=>  2}]}, 
        {"Sep 21"=> [{:applications_one=>  8}, {:applications_two=> 11}]},
        {"Oct 21"=> [{:applications_three=>7}, {:applications_one=>  1}]}
      ]
      

      我这样做的目的是展示我在下面建议的代码:

      • 不需要对日期字符串的值(数组)内的哈希值进行排序;
      • 不要求预先知道值内的哈希键的名称(例如,:applications_one);和
      • 允许日期字符串的值(数组)包含任意数量的哈希值。

      感兴趣的值可以如下计算。

      arr.each_with_object(Hash.new { |h,k| h[k] = [] }) do |g,h|
        date, a = g.flatten
        h[:dates] << date
        a.each do |f|
          label, value = f.flatten
          h[label] << value
        end
      end
        #=> {
        # :dates=>["May 21", "Jun 21", "Jul 21", "Aug 21", "Sep 21", "Oct 21"],
        # :applications_one=>[20, 15, 6, 1, 8, 1],
        # :applications_two=>[0, 0, 2, 11],
        # :applications_three=>[4, 7]
      }
      

      计算过程如下。

      最初,

      h = Hash.new { |h,k| h[k] = [] }
        #=> {}
      

      然后将第一个哈希传递给块(由块变量g保存)并执行块操作。

      g = {"May 21"=> [{:applications_one=> 20}, {:applications_two=> 0}]}
      
      date, a = g.flatten
        #=> ["May 21", [{:applications_one=>20}, {:applications_two=>0}]] 
        # therefore, date #=> "May 21" and
        # a #=> [{:applications_one=>20}, {:applications_two=>0}]]
      

      Hash#flatten

      h[:dates] << date
        # now h #=> {:dates=>["May 21"]}
      
      a.each do |f|
        puts "f=#{f}"
        label, value = f.flatten
        puts "label=#{label}, value=#{value}"
        h[label] << value
        puts "h=#{h}\n"
      end
      

      显示如下:

      f={:applications_one=>20}
      label=applications_one, value=20
      h={:dates=>["May 21"], :applications_one=>[20]}
      
      f={:applications_two=>0}
      label=applications_two, value=0
      h={:dates=>["May 21"], :applications_one=>[20], :applications_two=>[0]}
      

      arr 的下一个元素现在被传递到块并执行块计算。

      g #=> {"Jun 21"=> [{:applications_two=>  0}, {:applications_one=> 15}]}
      
      date, a = g.flatten
        #=> ["Jun 21", [{:applications_two=>0}, {:applications_one=>15}]]
        # therefore, date #=> "Jun 21" and
        # a #=> [{:applications_two=>0}, {:applications_one=>15}] 
      
      h[:dates] << date
        # now h #=> {:dates=>["May 21", "Jun 21"]}
      
      a.each do |f|
        puts "f=#{f}"
        label, value = f.flatten
        puts "label=#{label}, value=#{value}"
        h[label] << value
        puts "h=#{h}\n"
      end
      

      显示如下。

      f={:applications_two=>0}
      label=applications_two, value=0
      h={:dates=>["May21", "Jun21"], :applications_one=>[20], 
         :applications_two=>[0, 0]}
      
      f={:applications_one=>15}
      label=applications_one, value=15
      h={:dates=>["May21", "Jun21"], :applications_one=>[20, 15],
         :applications_two=>[0, 0]}
      

      其余的计算类似。

      注意,当arr 的第二个元素被传递到块时,

      h #=> {:dates=>["May 21"], :applications_one=>[20],
        #    :applications_two=>[0]} g[:date] #=> "Jun 21"
      

      以下计算非常有意义:

      h[:dates] << date
        #=> ["May 21"] << "Jun 21"
        #=> ["May 21", "Jun 21"]  
      

      相比之下,当arr的第一个元素被传递给块时,在h #=&gt; {}时进行了以下计算,因此h[:dates] #=&gt; nil

      h[:dates] << date
      h #=> {:dates=>["May 21"]}  
      

      您可能想知道为什么会这样,因为nil 没有方法&lt;&lt;。这是因为h 的定义方式:

      h = Hash.new { |h,k| h[k] = [] }
      

      查看Hash::new 的形式,它接受一个块(因此没有参数)。

      这意味着如果h 没有键k 并且可以通过操作更改,则首先执行分配h[k] = []。 (这不适用于例如m = h[k]; m #=&gt; nil,因为h 没有被更改。)

      处理后

      {"May 21"=> [{:applications_one=> 20}, {:applications_two=> 0}]}
      

      我们正在构建的哈希如下:

      h #=> {:dates=>["May 21"], :applications_one=>[20],
        #    :applications_two=>[0]}
      

      对于问题中给出的示例,返回以下内容:

      {:dates=>["May 21", "Jun 21", "Jul 21", "Aug 21"],
       :applications_one=>[20, 15, 8, 1],
       :applications_two=>[0, 0, 11, 2]}
      

      【讨论】:

      • 这真的很好,感谢简洁的描述性回复。非常感谢。我会试试这条路!
      猜你喜欢
      • 1970-01-01
      • 2014-01-02
      • 2013-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多