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]