2017-07-31 80 views
2

比较数组时,我有计数日期的三个数组:填充缺少的条目在Ruby中

first = [["July 01", "2"]["July 03", "2"]] 
second = [["June 30", "2"]["July 01", "2"]["July 02", "2"]] 
third = [["July 01", "2"]["July 02", "2"]] 

我想(没有成功)三个阵列相比,得到了全范围的日期,并注入失踪者为0结果存入别人......所以,在年底的每个阵列将具有启动于6月30日期条目,直到7月3日,像这样:

first = [["June 30", "0"]["July 01", "2"]["July 02", "0"]["July 03", "2"]] 
second = [["June 30", "2"]["July 01", "2"]["July 02", "2"]["July 03", "0"]] 
third = [["June 30", "0"]["July 01", "2"]["July 02", "2"]["July 03", "0"]] 

我尝试了一堆非常复杂的比较(像做演绎,存储为一个新的数组,然后使用该数组添加到缺少的但是当有两个以上的数组进行比较时,它变得非常复杂)和注入来做到这一点,但我认为必须有一个相对简单的方法来使用Ruby或Rails来实现。有任何想法吗?

回答

1

这里的另一种方式,用Date

require 'date' 

def compare_dates(*items) 
    all_dates = items.flatten(1).map { |d| Date.parse(d.first) } 
    str_dates = (all_dates.min..all_dates.max).map { |d| d.strftime("%B %d") } 

    items.map do |arr| 
    str_dates.map do |date| 
     current = arr.select { |e| e[0] == date }.flatten 
     current.empty? ? [date, "0"] : current 
    end 
    end 
end 

compare_dates(first, second, third) 
#=> [[["June 30", "0"], ["July 01", "2"], ["July 02", "0"], ["July 03", "2"]], 
# [["June 30", "2"], ["July 01", "2"], ["July 02", "2"], ["July 03", "0"]], 
# [["June 30", "0"], ["July 01", "2"], ["July 02", "2"], ["July 03", "0"]]] 

如果要覆盖每个数组的值,你可以这样做:

first, second, third = compare_dates(first, second, third) 

first 
#=> [["June 30", "0"], ["July 01", "2"], ["July 02", "0"], ["July 03", "2"]] 

second 
#=> [["June 30", "2"], ["July 01", "2"], ["July 02", "2"], ["July 03", "0"]] 

third 
#=> [["June 30", "0"], ["July 01", "2"], ["July 02", "2"], ["July 03", "0"]] 
+0

干净,简洁,美丽。谢谢格里。 – Ben

0

我有一个问题,为什么这是一个数组数组?如果你可以把它变成散列,问题处理起来很简单。它可以是这个样子:

first = {"july 01" => 2, "july 02" => 1} 
second = {"june 31" => 1, "july 01" => 1} 


keys = first.keys 
keys << second.keys 

keys.each do |key| 
    first[key] = first[key] || 0 
end 

我没有测试过这一点,这可能不是最有效的方式,但你可以在此之上进行优化。我希望有所帮助。

你也可以使用类似Convert array of 2-element arrays into a hash, where duplicate keys append additional values的东西将它转换成哈希。

+0

谢谢,但这并没有真正的帮助。我已经写了一些可以处理两个数组(或散列,无所谓)的东西。我需要一种方法来比较三个或更多数组并返回所需的结果,而不会太复杂。我想我可能会错过一个核心ruby方法开始。 – Ben

0

你可以把所有数组的联合,然后从它计算。

all = first | second | third 
#=> [["July 01", "2"], ["July 03", "2"], ["June 30", "2"], ["July 02", "2"]] 

(first | all).map { |k, v| first.include?([k, v]) ? [k, v] : [k, "0"] } 
      .sort_by { |i| [ Time.new(0, i[0][0..2]).month, i[0][-2..-1] ] } 

#=> [["June 30", "0"], ["July 01", "2"], ["July 02", "0"], ["July 03", "2"]] 
0
arr = [[["July 01", "2"], ["July 03", "2"]], 
     [["June 30", "2"], ["July 01", "2"], ["July 02", "2"]], 
     [["July 01", "2"], ["July 02", "2"]]] 

require 'date' 

default = arr.flatten(1). 
       map(&:first). 
       uniq. 
       sort_by { |s| Date.strptime(s, '%B %d') }. 
       product(['0']). 
       to_h 
    #=> {"June 30"=>"0", "July 01"=>"0", "July 02"=>"0", "July 03"=>"0"} 

arr.map { |a| default.merge(a.to_h).to_a } 
    #=> [[["June 30", "0"], ["July 01", "2"], ["July 02", "0"], ["July 03", "2"]], 
    # [["June 30", "2"], ["July 01", "2"], ["July 02", "2"], ["July 03", "0"]], 
    # [["June 30", "0"], ["July 01", "2"], ["July 02", "2"], ["July 03", "0"]]] 

的步骤如下。

b = arr.flatten(1) 
    #=> [["July 01", "2"], ["July 03", "2"], ["June 30", "2"], ["July 01", "2"], 
    # ["July 02", "2"], ["July 01", "2"], ["July 02", "2"]] 
c = b.map(&:first) 
    #=> ["July 01", "July 03", "June 30", "July 01", "July 02", "July 01", "July 02"] 
d = c.uniq 
    #=> ["July 01", "July 03", "June 30", "July 02"] 
e = d.sort_by { |s| Date.strptime(s, '%B %d') } 
    #=> ["June 30", "July 01", "July 02", "July 03"] 
f = e.product(['0']) 
    #=> [["June 30", "0"], ["July 01", "0"], ["July 02", "0"], ["July 03", "0"]] 
default = f.to_h 
    #=> {"June 30"=>"0", "July 01"=>"0", "July 02"=>"0", "July 03"=>"0"} 

为了计算

arr.map { |a| default.merge(a.to_h).to_a } 

arr第一值被传递到块和块变量a被设定为等于该值,并且执行块的计算。

a = arr.first 
    #=> [["July 01", "2"], ["July 03", "2"]] 
    g = a.to_h 
    #=> {"July 01"=>"2", "July 03"=>"2"} 
    h = default.merge(g) 
    #=> {"June 30"=>"0", "July 01"=>"2", "July 02"=>"0", "July 03"=>"2"} 
    h.to_a 
    #=> [["June 30", "0"], ["July 01", "2"], ["July 02", "0"], ["July 03", "2"]] 

arr其他值的计算是相似的。

计算d参见Date::strptime