简体   繁体   English

Rails:从 hashmap 检索键和值

[英]Rails: Retrieve keys and values from hashmap

I'm trying to retrieve two separate values with dates for a chart...我正在尝试用图表的日期检索两个单独的值...

 @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

I mapped it like this...我是这样映射的...

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

This gives...这给...

[
{"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}]} 
] 

I don't know how to get the values from this point.我不知道如何从这一点获得价值。 How would you extract the date keys and values like...?您将如何提取日期键和值,例如...?

Expected output:预期 output:

applications_one [20, 15, 8, 1] applications_one [20, 15, 8, 1]

applications_two [0, 0, 11, 2] applications_two [0, 0, 11, 2]

dates [May 21, Jun 21, Jul 21, Aug 21]日期 [5 月 21 日、6 月 21 日、7 月 21 日、8 月 21 日]

ty

Is that what you want to achieve?那是你想要达到的吗?

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 > 

I would do it a bit different.我会做的有点不同。 Would start by structuring the data this way:将从以这种方式构造数据开始:

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

This should give you:这应该给你:

@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} 
]

And then you would get your expected outputs like this:然后你会得到你的预期输出,如下所示:

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]

I've modified your example array as follows:我已将您的示例数组修改如下:

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}]}
]

My purpose in doing so is to show that the code I suggest below:我这样做的目的是展示我在下面建议的代码:

  • does not require the hashes within the values (arrays) of the date strings to be ordered;不需要对日期字符串的值(数组)中的哈希进行排序;
  • does not require the names of the keys of the hashes within the values (eg, :applications_one ) to be known in advance;不需要预先知道值中的哈希键的名称(例如:applications_one ); and
  • allows the values (arrays) of the date strings to contain any number of hashes.允许日期字符串的值(数组)包含任意数量的哈希。

The values of interest can be computed as follows.感兴趣的值可以如下计算。

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]
}

The calculations proceed as follows.计算如下进行。

Initially,最初,

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

The first hash is then passed to the block (held by the block variable g ) and block operations are performed.然后将第一个 hash 传递给块(由块变量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}]]

See Hash#flatten .请参阅哈希#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

The following is displayed:显示如下:

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]}

The next element of arr is now passed to the block and the block calculations are performed.现在将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

The following is displayed.显示以下内容。

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]}

The remaining calculations are similar.其余计算类似。

Note that when the second element of arr was passed to the block,请注意,当arr的第二个元素被传递到块时,

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

the following calculation makes perfect sense:以下计算非常有意义:

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

By contrast, when the first element of arr was passed to the block, the following calculation was performed when h #=> {} , and therefore h[:dates] #=> nil :相比之下,当arr的第一个元素被传递给块时,在h #=> {}时执行以下计算,因此h[:dates] #=> nil

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

You might wonder why this works, since nil does not have a method << .您可能想知道为什么这会起作用,因为nil没有方法<< It's because of the way h was defined:这是因为h的定义方式:

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

See the form of Hash::new that takes a block (and therefore no argument).请参阅采用块(因此没有参数)的Hash::new的形式。

What this means is that if h does not have a key k and may be altered by operation, the assignment h[k] = [] is performed first.这意味着如果h没有键k并且可以通过操作更改,则首先执行分配h[k] = [] (This does not apply to, for example, m = h[k]; m #=> nil , as h is not being altered.) (这不适用于例如m = h[k]; m #=> nil ,因为h没有被改变。)

After having processed处理后

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

the hash we are building is as follows:我们正在构建的 hash 如下:

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

For the example given in the question the following is returned:对于问题中给出的示例,将返回以下内容:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM