求和散列数组中哈希的下一个值

时间:2016-05-23 01:34:36

标签: ruby-on-rails arrays ruby hash

我有一系列像这样的哈希:

[{Mon, 09 May 2016 14:49:17 UTC +00:00=>12}, 
{Sun, 17 Apr 2016 14:08:40 UTC +00:00=>30}, 
{Sun, 16 Apr 2016 14:08:40 UTC +00:00=>18}, 
{Sun, 15 Apr 2016 14:03:33 UTC +00:00=>21}]

如何将从最早的日期到当前日期的先前值相加,我的预期输出将是:

[{Mon, 09 May 2016 14:49:17 UTC +00:00=>81}, 
{Sun, 17 Apr 2016 14:08:40 UTC +00:00=>69}, 
{Sun, 16 Apr 2016 14:08:40 UTC +00:00=>39}, 
{Sun, 15 Apr 2016 14:03:33 UTC +00:00=>21}]

谢谢!

3 个答案:

答案 0 :(得分:1)

假设数组中每个哈希的键都是DateTime个对象,你可以得到你想要的东西:

balance = [
  {DateTime.parse('Mon, 09 May 2016 14:49:17 UTC +00:00')=>12}, 
  {DateTime.parse('Sun, 17 Apr 2016 14:08:40 UTC +00:00')=>30}, 
  {DateTime.parse('Sun, 16 Apr 2016 14:08:40 UTC +00:00')=>18}, 
  {DateTime.parse('Sun, 15 Apr 2016 14:03:33 UTC +00:00')=>21}
] # => your original array     

# Get expected array.
balance.map{ |h| 
  { 
    h.keys.first => balance.select{ |e| 
                      e.keys.first <= h.keys.first }.map{ |s| 
                        s[s.keys.first] }.reduce(:+) 
  } 
} 

我将代码分成行以提高可读性。

答案 1 :(得分:1)

另一种方法是首先sort数组,然后使用map函数保持运行总数以收集所需数据。

# sort the balances by date
balance = balance.sort {|a, b| a.keys.first <=> b.keys.first }

# get running total and collect for each date
total = 0
balance.map do |entry|
  date, value = entry.first
  total += value
  {date => total}
end

答案 2 :(得分:1)

我认为你的数组是最新的日期顺序,看起来像下面的arr

a = [{ "Mon, 09 May 2016 14:49:17 UTC +00:00"=>12 }, 
     { "Sun, 17 Apr 2016 14:08:40 UTC +00:00"=>30 }, 
     { "Sun, 16 Apr 2016 14:08:40 UTC +00:00"=>18 }, 
     { "Sun, 15 Apr 2016 14:03:33 UTC +00:00"=>21 }]

require 'date'
arr = a.map do |h|
  (d, v) = h.to_a.first
  { DateTime.parse(d) => v }
end
  #=> [{#<DateTime: 2016-05-09T14:49:17+00:00 ((2457518j,53357s,0n),+0s,2299161j)>=>12},
  #    {#<DateTime: 2016-04-17T14:08:40+00:00 ((2457496j,50920s,0n),+0s,2299161j)>=>30},
  #    {#<DateTime: 2016-04-16T14:08:40+00:00 ((2457495j,50920s,0n),+0s,2299161j)>=>18},
  #    {#<DateTime: 2016-04-15T14:03:33+00:00 ((2457494j,50613s,0n),+0s,2299161j)>=>21}] 

然后我们可以按如下方式计算所需的数组。

cumv = 0
arr.reverse.
    map { |h| h.to_a.first }.
    each_with_object([]) do |(d,v),a|
      cumv += v
      a << { d => cumv }
    end.
    reverse
  #=> [{#<DateTime: 2016-05-09T14:49:17+00:00 ((2457518j,53357s,0n),+0s,2299161j)>=>81},
  #    {#<DateTime: 2016-04-17T14:08:40+00:00 ((2457496j,50920s,0n),+0s,2299161j)>=>69},
  #    {#<DateTime: 2016-04-16T14:08:40+00:00 ((2457495j,50920s,0n),+0s,2299161j)>=>39},
  #    {#<DateTime: 2016-04-15T14:03:33+00:00 ((2457494j,50613s,0n),+0s,2299161j)>=>21}]