我有一个名为interval的数组。我希望从中构建一个哈希数组,为每个哈希(start_ts和stop_ts)添加两个键/值对。
require 'date'
date = '2014-06-12'
totalhash = Hash.new
totalarray = Array.new
payload2 = Array.new
totals = Array.new
intervals = [["Current", 0, 9999],
["1 to 4", -4, -1],
["5 to 15", -15, -5],
["16 to 30", -30, -16],
["31 to 60", -60, -31],
["61 to 90", -90, -61],
["91+", -9999, -91]]
intervals.each do |int|
label, start, stop = int
# Parse date and then convert to UNIX epoch (.to_time.to_i chain)
start_ts = (Date.parse("#{date}") + start).to_time.to_i
stop_ts = (Date.parse("#{date}") + stop).to_time.to_i
totalhash[:label] = label
totalhash[:start] = start
totalhash[:stop] = stop
totalhash[:start_ts] = start_ts
totalhash[:stop_ts] = stop_ts
totalarray << totalhash
totals = totalarray.reduce Hash.new, :merge
puts totals
puts 'totals size: ' + totals.size.to_s
end
最终结果应该是七个哈希的数组。目前,数组totalarray似乎在每次传递时被覆盖而不是被附加到。
我做错了什么。感谢。
答案 0 :(得分:1)
当您想要数组的1对1输出时,请使用map
。它减少了对所有这些中间变量的需求。
# Parse date outside the loop as per @Uri's comment
day = Date.parse(date)
t = intervals.map do |interval|
label, start, stop = interval
{
label: label,
start: start,
stop: stop,
start_ts: (day + start).to_time.to_i,
stop_ts: (day + stop).to_time.to_i
}
end
这会产生您想要的七哈希数组。
至于您获得的单个哈希输出:您的reduce
行是罪魁祸首。我不确定你在那里做什么。
答案 1 :(得分:0)
此:
totalarray << totalhash
不会复制totalhash
,它只会附加对totalarray
末尾的引用。说:
totalarray << {
# build the Hash inline right here
}
您的代码最终会intervals.length
引用totalarray
中完全相同的哈希值。然后你的reduce
将Hash合并到自身中,这没有任何用处。实际上,即使totals = totalarray.reduce Hash.new, :merge
已正确构建,您的totalarray
也没有任何用处,您可以说totals = totalarray.last
并获得相同的结果。
答案 2 :(得分:0)
我通常会这样做:
myArray = [['cow','moo'],['dog','woof'],['duck','quack'],['fox','?']]
myArray.collect! do |animal|
animal = {animal[0]=>animal[1]}
end
puts myArray.inspect
我不熟悉reduce
或inject
来评论您在此处的使用情况。但是这里是您原始代码的编辑版本,我认为可以满足您的需求:
require 'date'
date = '2014-06-12'
#totalhash = Hash.new
totalarray = Array.new
payload2 = Array.new
totals = Array.new
intervals = [["Current", 0, 9999],
["1 to 4", -4, -1],
["5 to 15", -15, -5],
["16 to 30", -30, -16],
["31 to 60", -60, -31],
["61 to 90", -90, -61],
["91+", -9999, -91]]
intervals.each do |int|
totalhash = Hash.new #moved your hash creation here, in the iteration
label, start, stop = int
# Parse date and then convert to UNIX epoch (.to_time.to_i chain)
start_ts = (Date.parse("#{date}") + start).to_time.to_i
stop_ts = (Date.parse("#{date}") + stop).to_time.to_i
totalhash[:label] = label
totalhash[:start] = start
totalhash[:stop] = stop
totalhash[:start_ts] = start_ts
totalhash[:stop_ts] = stop_ts
totalarray << totalhash
#totals = totalarray.reduce Hash.new, :merge
#puts totals
#puts 'totals size: ' + totals.size.to_s
end
puts totalarray.inspect #see the array object as is using 'inspect'
〜
答案 3 :(得分:0)
我建议您考虑更改数据结构。我不认为在每个哈希中包含自纪元以来的计算时间是明智的;相反,只需使用辅助方法计算这些值:
require 'date'
date = Date.parse('2014-06-12')
#=> #<Date: 2014-06-12 ((2456821j,0s,0n),+0s,2299161j)>
def start_stop_to_time(d, date)
(date + d).to_time.to_i
end
例如,
start_stop_to_time(-4, date) #=> 1402210800
然后 total_array
:
total_array = [[:label, :start, :stop]].product(intervals)
.map { |k,v| k.zip(v).to_h }
#=> [{:label=> "Current", :start=> 0, :stop=>9999},
# {:label=> "1 to 4", :start=> -4, :stop=> -1},
# {:label=> "5 to 15", :start=> -15, :stop=> -5},
# {:label=>"16 to 30", :start=> -30, :stop=> -16},
# {:label=>"31 to 60", :start=> -60, :stop=> -31},
# {:label=>"61 to 90", :start=> -90, :stop=> -61},
# {:label=> "91+", :start=>-9999, :stop=> -91}]
我不明白totals
的目的,所以我不能对此发表评论。