我有一系列哈希:
items = [
{:created=>"2013-12-01", :amount=>16611},
{:created=>"2013-12-02", :amount=>16611},
{:created=>"2013-12-04", :amount=>9428},
{:created=>"2013-12-05", :amount=>11628},
{:created=>"2013-12-06", :amount=>4600},
{:created=>"2013-12-09", :amount=>21756},
{:created=>"2013-12-10", :amount=>18127}
]
您会注意到,序列中缺少许多日期(3,7和8)。
我有map
将这些哈希值输出到只包含与日期范围匹配的哈希值的数组中:
items.select{ |key| (Date.parse("December 1, 2013")..Date.parse("December 12, 2013")).include? Date.parse(key[:created])}.map { |key| key[:amount] }
现在,它将amount
项的全部内容输出到一个数组中:[16611, 16611, 9428, 11628, 4600, 21756, 18127]
但我需要它做的是为范围中缺少的日期插入0
。所以在我的例子中,我的范围从12月1日到12月12日。所以输出将是:
[16611, 16611, 0, 9428, 11628, 4600, 0, 0, 21756, 18127, 0, 0]
我该怎么做?
答案 0 :(得分:1)
因为每个人都喜欢单行:
Hash[(Date.parse("December 1, 2013")..Date.parse("December 12, 2013")).map { |x| [x,{:created=>x,:amount=>0}]}+ items.map { |x| [Date.parse(x[:created]),x] }].map { |i| i[1][:amount]}
基本上,使用空值创建我们想要的日期数组,将实际值添加到数组的末尾。转换为哈希值,从而覆盖它们存在的早期空值,然后迭代结果。在Ruby> = 1.9.2中,您可以按原始顺序获取密钥。
[16611, 16611, 0, 9428, 11628, 4600, 0, 0, 21756, 18127, 0, 0]
答案 1 :(得分:0)
lookup = Hash[*items.flat_map { |it| [Date.parse(it[:created]),it[:amount]] }]
(0..11).map { |i| lookup.fetch(Date.new(2013,12,1)+i,0) }
[16611,16611,0,9428,11628,4600,0,0,21756,18127,0,0]
答案 2 :(得分:0)
给定日期范围:
r = (Date.parse("December 1, 2013")..Date.parse("December 12, 2013"))
并假设items
中的日期是唯一的,看起来就是这种情况,我会这样做:
b = items.each_with_object({}) {|g,h| h[Date.parse(g[:created])] = g[:amount]}
r.map { |d| b[d] ? b[d] : 0 }
#=> [16611, 16611, 0, 9428, 11628, 4600, 0, 0, 21756, 18127, 0, 0]
我们首先使用元素k=>v
创建一个哈希,每个哈希都对应h
items
的元素k = Date.parse(h[:created])
,以便v = h[:amount]
和b = items.each_with_object({}) {|g,h| h[Date.parse(g[:created])] = g[:amount]}
#=> {#<Date: 2013-12-01 ((2456628j,0s,0n),+0s,2299161j)>=>16611,
# #<Date: 2013-12-02 ((2456629j,0s,0n),+0s,2299161j)>=>16611,
# #<Date: 2013-12-04 ((2456631j,0s,0n),+0s,2299161j)>=> 9428,
# #<Date: 2013-12-05 ((2456632j,0s,0n),+0s,2299161j)>=>11628,
# #<Date: 2013-12-06 ((2456633j,0s,0n),+0s,2299161j)>=> 4600,
# #<Date: 2013-12-09 ((2456636j,0s,0n),+0s,2299161j)>=>21756,
# #<Date: 2013-12-10 ((2456637j,0s,0n),+0s,2299161j)>=>18127}
:
map
如果d
包含密钥r
,我们会使用b[d]
将b
范围内的每个成员d
转换为d
,否则items.each_with_object({}) {
|g,h| h[Date.parse(g[:created])] = g[:amount] }
.values_at(*(rng.to_a))
.map {|v| v.nil? ? 0 : v}
转换为零。
或者,我们可以这样做:
nil
如上所述计算哈希后,我们使用Hash#values_at创建一个包含哈希值的数组,并为rng
中的每个日期添加b
,但没有匹配在c = items.each_with_object({}) {|g,h|
h[Date.parse(g[:created])] = g[:amount]}.values_at(*rng.to_a)
#=> [16611, 16611, nil, 9428, 11628, 4600, nil, nil, 21756, 18127, nil, nil]
:
nil
最后,将c.map {|v| v.nil? ? 0 : v}
#=> [16611, 16611, 0, 9428, 11628, 4600, 0, 0, 21756, 18127, 0, 0]
s映射到零:
{{1}}