Rails:从哈希图中检索键和值
Rails: Retrieve keys and values from hashmap
我正在尝试为图表检索两个带有日期的单独值...
@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 日]
有
这是你想要达到的目标吗?
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 >
我会做一些不同的事情。将从以这种方式构建数据开始:
@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]
我已将您的示例数组修改如下:
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
的第二个元素传给block时,
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 #=> {}
时进行了以下计算,因此h[:dates] #=> nil
:
h[:dates] << date
h #=> {:dates=>["May 21"]}
您可能想知道为什么会这样,因为 nil
没有方法 <<
。这是因为 h
的定义方式:
h = Hash.new { |h,k| h[k] = [] }
参见 Hash::new 的形式,它采用一个块(因此没有参数)。
意思是如果h
没有keyk
,可以通过操作改变,则先赋值h[k] = []
。 (这不适用于 m = h[k]; m #=> 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]}
我正在尝试为图表检索两个带有日期的单独值...
@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 日]
有
这是你想要达到的目标吗?
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 >
我会做一些不同的事情。将从以这种方式构建数据开始:
@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]
我已将您的示例数组修改如下:
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
的第二个元素传给block时,
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 #=> {}
时进行了以下计算,因此h[:dates] #=> nil
:
h[:dates] << date
h #=> {:dates=>["May 21"]}
您可能想知道为什么会这样,因为 nil
没有方法 <<
。这是因为 h
的定义方式:
h = Hash.new { |h,k| h[k] = [] }
参见 Hash::new 的形式,它采用一个块(因此没有参数)。
意思是如果h
没有keyk
,可以通过操作改变,则先赋值h[k] = []
。 (这不适用于 m = h[k]; m #=> 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]}