【问题标题】:Rails Merge Hash & Array with different KeysRails 使用不同的键合并哈希和数组
【发布时间】:2013-06-13 17:14:43
【问题描述】:

如果我有一系列月份,例如:

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

因此需要注意的是,如果范围超出,例如两年,则数组将具有重复的月份值。我想我需要将年份添加到该数组中?

有没有更好的方法来做到这一点?

这里的最终目标是为 highcharts 获取散列或数组,以显示特定车辆的每月燃料使用总量。 (只是让你有一些背景)。

【问题讨论】:

  • 以编程方式,带有循环。没有神奇的方法可以做到这一点。你试过什么?
  • 问题不清楚。 1. 告诉第一个{"05" ...} 应该有"20" 而不是第二个的规则是什么? 2. {"06" ...} 是按照什么规则插入到预期输出中的?这里有系统的规律,还是只是你的马虎?
  • 您似乎随意地将“06”从第二个元素移动到了最后一个元素。
  • 对不起,这只是一个粗略的例子——所以是的,任意的。
  • 这不是一个真正的问题吗?

标签: ruby-on-rails arrays hash merge


【解决方案1】:

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

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

【讨论】:

  • 这很好,而且有效。根据我的编辑,您可以编辑以删除排序吗?
  • 看到您的编辑。是的,如果您有重复的月份,这将是一个问题。最终产品不能是数组,因为键必须是唯一的。得想想这个……
  • 或许我只需要将日期数组设为“m-yyyy”?
猜你喜欢
  • 1970-01-01
  • 2018-02-12
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
相关资源
最近更新 更多