在Ruby中比较数组时填充缺少的条目

时间:2017-07-31 18:17:18

标签: ruby-on-rails 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。有什么想法吗?

4 个答案:

答案 0 :(得分: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"]]

答案 1 :(得分: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之类的内容将其转换为哈希。

答案 2 :(得分: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"]]

答案 3 :(得分: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