Rails Merge Hash&具有不同键的数组

时间:2013-06-17 16:52:33

标签: ruby-on-rails arrays hash merge

如果我有几个月的数组:

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

一个月值的哈希值和month_sum:

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

如何将哈希值合并到数组中,以便得到类似的内容?

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

修改

月份数组来自:

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

所以需要注意的是,如果范围结束,比如两年,则数组将具有重复的月值。我想我需要将年份添加到该数组中?

有更好的方法吗?

此处的最终目标是获取高速图表的哈希值或数组,以显示特定车辆的每月燃料使用量。 (只是你有一些背景)。

1 个答案:

答案 0 :(得分:3)

试试这个。请注意,最终产品是哈希,而不是哈希数组。但我认为在这种情况下哈希更容易使用。

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

编辑(根据新信息)

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