लापता मूल्यों के साथ हैश की एक सरणी भरें
मैं ApexChart के लिए कुछ हीटमैप विनिर्देश चार्ट बनाने की कोशिश कर रहा हूं । अब तक, मुझे हश का यह एरे मिला, 3 गतिविधियों के लिए।
[{
:name => "Activity 1",
:data => {
"May 2020" => 37, "June 2020" => 17, "July 2020" => 9, "August 2020" => 18
}
}, {
:name => "Activity 2",
:data => {
"May 2020" => 3
}
}, {
:name => "Activity 3",
:data => {
"July 2020" => 5, "November 2020" => 11
}
}]
गतिविधि 3 पर, हमें केवल 2 महीने मिले जो हैं, July
और November
।
मेरी आवश्यकता प्रत्येक हैश के लिए, सभी लापता तारीखों को भरने के लिए होगी, और उन्हें मान के रूप में 0 से भरना होगा। मेरे प्रतीक्षित परिणाम होंगे
[{
:name => "Activity 1",
:data => {
"May 2020" => 37, "June 2020" => 17, "July 2020" => 9, "August 2020" => 18, "November 2020" => 0
}
}, {
:name => "Activity 2",
:data => {
"May 2020" => 3, "June 2020" => 0, "July 2020" => 0, "August 2020" => 0, "November 2020" => 0
}
}, {
:name => "Activity 3",
:data => {
"May 2020" => , "June 2020" => 0, "July 2020" => 5, "August 2020" => 0, "November 2020" => 11
}
}]
हां, September
उद्देश्य से गायब है। मुझे लगता है कि इसे प्राप्त करने का सबसे अच्छा तरीका हर महीने, एक-एक करके प्राप्त करना होगा; फिर लापता महीनों के साथ प्रत्येक सरणियों को भरने के लिए; लेकिन मुझे नहीं पता कि इसे कैसे हासिल किया जाए।
जवाब
यदि arr
आपके पास हैश की सरणी है, तो आप दो चरणों में वांछित सरणी का निर्माण कर सकते हैं।
require 'date'
date_fmt = "%B %Y"
first_month, last_month = arr.flat_map do |g|
g[:data].keys
end.map { |s| Date.strptime(s, date_fmt) }.minmax
#=> [#<Date: 2020-05-01 ((2458971j,0s,0n),+0s,2299161j)>,
# #<Date: 2020-11-01 ((2459155j,0s,0n),+0s,2299161j)>]
h = (first_month..last_month).map do |d|
d.strftime(date_fmt)
end.product([0]).to_h
#=> {"May 2020"=>0, "June 2020"=>0, "July 2020"=>0, "August 2020"=>0,
# "September 2020"=>0, "October 2020"=>0, "November 2020"=>0}
arr.map { |g| g.merge(:data => h.merge(g[:data])) }
#=> [
# {
# :name=>"Activity 1",
# :data=>{
# "May 2020"=>37, "June 2020"=>17, "July 2020"=>9,
# "August 2020"=>18, "September 2020"=>0,
# "October 2020"=>0, "November 2020"=>0
# }
# },
# {
# :name=>"Activity 2",
# :data=>{
# "May 2020"=>3, "June 2020"=>0, "July 2020"=>0,
# "August 2020"=>0, "September 2020"=>0,
# "October 2020"=>0, "November 2020"=>0
# }
# },
# {
# :name=>"Activity 3",
# :data=>{
# "May 2020"=>0, "June 2020"=>0, "July 2020"=>5,
# "August 2020"=>0, "September 2020"=>0,
# "October 2020"=>0, "November 2020"=>11
# }
# }
# ]
देखें Enumerable # flat_map , दिनांक :: strptime , सरणी # minmax , दिनांक # strftime , सरणी # उत्पाद और हैश # मर्ज । दिनांक स्वरूपण निर्देशों के लिए दिनांक समय # तारीख भी देखें ।
ध्यान दें कि की गणना में first_month
और last_month
,
[#<Date: 2020-05-01 ((2458971j,0s,0n),+0s,2299161j)>,
#<Date: 2020-11-01 ((2459155j,0s,0n),+0s,2299161j)>].
map { |d| d.strftime(date_fmt) }
#=> ["May 2020", "November 2020"]
आप पहले महीनों को प्राप्त करके और फिर अपने मामले में हैश आइटम को संशोधित करके कुछ इसी तरह प्राप्त कर सकते हैं:
months = data.flat_map { |d| d[:data].keys }.to_set
data.each do |d|
months.each do |month|
d[:data][month] = 0 unless d[:data].key?(month)
end
end
आप जो भी कर सकते हैं वह एक नया बनाने के लिए है Array
जहां Hash
मूल्यों को एक डिफ़ॉल्ट मान के साथ आरंभ किया जाता है:
data_with_default = data.map do |d|
{
name: d[:name],
data: Hash.new(0).update(d[:data])
}
end
निम्नलिखित प्रयास करें:
a = [{
:name => "Activity 1",
:data => {
"May 2020" => 37, "June 2020" => 17, "July 2020" => 9, "August 2020" => 18
}
}, {
:name => "Activity 2",
:data => {
"May 2020" => 3
}
}, {
:name => "Activity 3",
:data => {
"July 2020" => 5, "November 2020" => 11
}
}]
months = ['May 2020', 'June 2020', 'July 2020', 'August 2020', 'November 2020']
puts a.map { |h| { name: h[:name], data: Hash[months.map { |m| [m, h[:data][m] ? h[:data][m] : 0] }] } }