2015-07-13 35 views
5

下面的哈希函數是否更容易轉置?我有一個解決方案,但轉置方法很難閱讀。用例是作業(j1,j2,j3等)的散列和它們發生在(d1,d2,d3等)上的日期。需要做一些事件(e1,e2,e3等),這些事件按日期,然後作業分組,然後將它們轉換爲分組爲作業,然後是日期用zip壓縮紅寶石中的哈希值

我用#zip方法進行了實驗,但是需要在j1:d1處注入nil,然後將它們從結果中剝離出來。我也努力尋找具有塊參數的#zip的示例用法。我明白#zip with a block always returns nil,但結果我不明白你將如何實際使用它。

require 'rspec' 
require 'pry' 

#  | d1 | d2 | d3 | 
#  ---------------------- 
# j1 |  | e2 | e3 | 
# -------------------------- 
# j2 | e4 | e5 | e6 | 
# -------------------------- 
# j3 | e7 |  | e9 | 
# -------------------------- 

def transpose(h) 
    Hash[ 
    dates(h).map do |d| 
     [ 
     d, 
     Hash[ h.keys.map do |j| 
      h[j][d] ? [j, h[j][d]] : nil 
     end.compact ] 
     ] 
    end 
    ] 
end 

def dates(h) 
    h.values.map(&:keys).reduce(:|).sort 
end 

describe "transpose" do 

    let(:starting) { 
    { 
     j1: { d2: :e2, d3: :e3 }, 
     j2: { d1: :e4, d2: :e5, d3: :e6 }, 
     j3: { d1: :e7, d3: :e9 } 
    } 
    } 

    let(:transposed) { 
    { 
     d1: { j2: :e4, j3: :e7 }, 
     d2: { j1: :e2, j2: :e5 }, 
     d3: { j1: :e3, j2: :e6, j3: :e9 } 
    } 
    } 

    it { expect(dates(starting)).to eq([:d1, :d2, :d3]) } 
    it { expect(transpose(starting)).to eq(transposed) } 
end 
+2

我希望在這裏的每個問題都是這樣的。一個很好的代碼示例,包含測試。 – Yule

+0

雖然很難遵循你的描述 - 我認爲你在'array'這個地方使用了單詞'hash',它是正確的嗎? ('作業散列','日期散列') - 儘管在最後的例子清除了它。 :) – BroiSatse

+0

謝謝@Yule。寫作問題本身就是一門藝術! –

回答

2

我已經重寫你的transpose方法了一下,應該是更快,更清潔:

def transpose(h) 
    h.each_with_object({}) do |(outer, data), ret| 
     data.each do |inner, event| 
     ret[inner] = {} unless ret[inner] 
     ret[inner][outer] = event 
     end 
    end 
    end 

它不使用日期的不必要的映射,是雙向的(改變內外鍵)。讓我知道你的想法:)

+0

美麗!使用測試問一個問題的好處是您可以複製和粘貼代碼以查看測試是否通過:)這比我的解決方案要乾淨得多。謝謝。 ➜SD GIT中:(PT98271602_scrollable_calendar)✗rspec的./stack_overflow_question.rb .. 在0.00393秒成品 2實施例中,0失敗 –