Ruby 如何映射哈希数组并在空日期项上输出0?

Ruby 如何映射哈希数组并在空日期项上输出0?,ruby,arrays,hash,Ruby,Arrays,Hash,我有一个哈希数组: 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-

我有一个哈希数组:

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)

我有一个
映射
,它将这些哈希值输出到一个数组中,该数组只包含与一系列日期匹配的哈希值:

items.select{ |key| (Date.parse("December 1, 2013")..Date.parse("December 12, 2013")).include? Date.parse(key[:created])}.map { |key| key[:amount] }
现在,它将
金额
项的全部内容输出到一个数组中:
[16611、16611、9428、11628、4600、2175618127]

但我需要它做的是为范围中缺少的日期插入一个
0
。在我的例子中,我的范围是从12月1日到12月12日。因此,输出将是:

[16611, 16611, 0, 9428, 11628, 4600, 0, 0, 21756, 18127, 0, 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、09428、11628、4600、0、0、2175618127、0、0]


因为每个人都喜欢一行:

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]
给定日期范围:

r = (Date.parse("December 1, 2013")..Date.parse("December 12, 2013"))
假设
项目
中的日期是唯一的(似乎是这样),我会这样做:

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
,这样
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}
如上所述计算散列后,我们使用创建一个数组,其中包含散列中的值,加上
rng
中每个日期的
nil
,而
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
s映射为零:

c.map {|v| v.nil? ? 0 : v}
  #=> [16611, 16611, 0, 9428, 11628, 4600, 0, 0, 21756, 18127, 0, 0]

美好的出于好奇,有没有一种方法可以在一行中实现这一点?
(0..11).映射{i |(items.find{t | t[:created]==Date.new(2013,12,1+i).to|{}[:amount][amount| | 0}
实际上,如果使用ruby>1.9.2,这是完全安全的。Ruby>1.9.2保留键顺序。Matt的答案更优雅。may|fail | | | safe| default的使用很棒。受@Matt answer的启发,
(Date.parse(“2013年12月1日”)…Date.parse(“2013年12月12日”)。map{d |(items.find(Proc.new{:created=>d.to|s,:amount=>0}{t.to|d.to| s==t[:created]})[:amount code>为日期创建缺失的哈希,如果您想要返回多个字段,那么这可能很有用。
c.map {|v| v.nil? ? 0 : v}
  #=> [16611, 16611, 0, 9428, 11628, 4600, 0, 0, 21756, 18127, 0, 0]