0

If I have an array of months like:

["05", "06", "07", "08", "09", "10", "11", "12", "01", "02", "03", "04", "05"]

And a hash of a month value and a month_sum:

[{"month"=>5, "month_sum"=>20}, {"month"=>4, "month_sum"=>100}]

How do I merge the hash into the array so I get something like?

[{"05" => 20}, {"07" => 0}, {"08" => 0}, {"09" => 0}, {"10" => 0}, {"11" => 0}, {"12" => 0}, {"01" => 0}, {"02" => 0}, {"03" => 0}, {"04" => 100}, {"05" => 0}, {"06" => 0}]

Edit

The month array is generated from:

date_from  = Date.parse(params[:search][:date_from])
date_to    = Date.parse(params[:search][:date_to])
date_range = date_from..date_to

date_months = date_range.map {|d| Date.new(d.year, d.month, 1) }.uniq
@date_range = date_months.map {|d| d.strftime "%m" }

So a caveat is that if the range is over, say a two year period, the array will have duplicate month-values. I suppose I need to add the year into that array?

Is there a better way to do this?

The end goal here is to get a hash or array for highcharts to display monthly sums of fuel usage for particular vehicles. (just so you have some context).

5
  • 2
    Programatically, with loops. There is no magic method to do so. What have you tried? Commented Jun 17, 2013 at 16:55
  • Question is not clear. 1. What is the rule that tells the first {"05" ...} should have "20" and not the second one? 2. By what rule is {"06" ...} inserted into the expected output? Is there a systematic rule here, or is it just your sloppiness? Commented Jun 17, 2013 at 17:06
  • You've also moved a "06" from the 2nd element to the last element, seemingly arbitrarily. Commented Jun 17, 2013 at 17:11
  • Sorry, This is just a rough example--so yes, arbitrarily. Commented Jun 17, 2013 at 18:01
  • How is this not a real question? Commented Jun 17, 2013 at 18:09

1 Answer 1

3

Try this. Note the final product is a hash, not an array of hashes. But I think a hash is easier to work with in this case.

# starting variables
array_of_months = ["05", "06", "07", "08", "09", "10", "11", "12", "01", "02", "03", "04", "05"]
month_sums = [{"month"=>5, "month_sum"=>20}, {"month"=>4, "month_sum"=>100}]

# clean up array_of_months
months = array_of_months.compact.sort
=> ["01", "02", "03", "04", "05", "05", "06", "07", "08", "09", "10", "11", "12"]

# compress month_sums into single key/value pairs such that first value becomes the key and second value becomes the value
sums = month_sums.inject({}) { |a, ms| a.merge!("%02d" % ms['month'] => ms['month_sum']) }
=> { "05" => 20, "04" => 100 }

# generate hash of all months and match sums value if key is present otherwise assign value zero
all_month_sums = months.inject({}) { |h, m| h.merge!(m => sums[m] || 0) }
=> {"01"=>0, "02"=>0, "03"=>0, "04"=>100, "05"=>20, "06"=>0, "07"=>0, "08"=>0, "09"=>0, "10"=>0, "11"=>0, "12"=>0}

EDIT (in light of new information)

# starting variables
months = ["05", "06", "07", "08", "09", "10", "11", "12", "01", "02", "03", "04", "05"]
month_sums = [{"month"=>5, "month_sum"=>20}, {"month"=>4, "month_sum"=>100}, {"month" => 5, "month_sum" => 99 }]

# iterate each month, select the first match, remove the match when done. if no match just give month a zero.
months.inject([]) do |a, month|
  if s = month_sums.select { |s| month.to_i == s['month'] }.first
    a << { "%02d" % s['month'] => s['month_sum'] }
    s['month'] = nil
  else
    a << { month => 0 }
  end
  a
end
=> [{"05"=>20}, {"06"=>0}, {"07"=>0}, {"08"=>0}, {"09"=>0}, {"10"=>0}, {"11"=>0}, {"12"=>0}, {"01"=>0}, {"02"=>0}, {"03"=>0}, {"04"=>100}, {"05"=>99}]
Sign up to request clarification or add additional context in comments.

3 Comments

This is good and it works. Per my edit, can you edit to remove the sort?
Saw your edit. Yeah, this would be a problem if you have duplicate months. And the end product couldn't be an array because the keys have to be unique. Gotta think about this...
Perhaps I just need to make the date array 'm-yyyy'?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.