2017-07-31 125 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