2012-06-22 64 views
0

代碼排序兩個輸入序列 - seq01和seq02 - 其timestamp值的基礎上,並返回表示該序列要被讀取的值是在順序的序列。錯誤合併時間戳的兩個序列,得到串

對於那些seq02的時間戳值大於seq01的時間戳值較小的情況下,我們得到返回「2」的順序,否則「1」。這些表示在該點seq01將被採用還是採用seq02來使數據按順序(通過時間戳值)。

let mergeSeq (seq01:seq<_>) (seq02:seq<_>) = 
    seq { 
      use iter01 = seq01.GetEnumerator() 
      use iter02 = seq02.GetEnumerator() 
      while iter01.MoveNext() do 
       let _,_,time01 = iter01.Current 
       let _,_,time02 = iter02.Current 
       while time02 < time01 && iter02.MoveNext() do 
        yield "2" 
       yield "1" 
    } 

要在FSI測試它創建了兩個序列a和b中,a = {1; 3; 5; ...}且b = {0; 2; 4; ...}。因此,let c = mergeSeq a b的預期值將爲{「2」,「1」,「2」,「1」...}。但是我得到這個錯誤:error FS0001: The type ''a * 'b * 'c' does not match the type 'int'

編輯

修正後:

let mergeSeq (seq01:seq<_>) (seq02:seq<_>) = 
    seq { 
      use iter01 = seq01.GetEnumerator() 
      use iter02 = seq02.GetEnumerator() 
      while iter01.MoveNext() do 
       let time01 = iter01.Current 
       let time02 = iter02.Current 
       while time02 < time01 && iter02.MoveNext() do 
        yield "2" 
       yield "1" 
    } 

運行此之後,還有另一個錯誤:call MoveNext。不知何故迭代沒有被執行。

EDIT 2

let mergeRef (seq01:seq<_>) (seq02:seq<_>) = 
    seq{ 
      use iter01 = seq01.GetEnumerator() 
      use iter02 = seq02.GetEnumerator() 
      iter01.MoveNext() 
      iter02.MoveNext() 

      let temp01 = ref iter01.Current //!!using mutable reference 
      let temp02 = ref iter02.Current 

      while iter01.MoveNext() do 
       while (iter02.MoveNext()) && ((!temp02) < (!temp01)) do 
        temp02 := iter02.Current 
        yield "2" 
       yield "1" 
       temp01 := iter01.Current 

      //if seq01 finishes before seq02 
      while iter02.MoveNext() do 
       yield "2" 

     } 

回答

2

編輯後...

你需要訪問當前之前調用的MoveNext 2。在內循環中移動2時,您不會更新time02。而且你沒有正確地檢查序列的結尾(例如,如果2結束,但1結束,你將嘗試在結束後訪問2)。

(這個功課是?)

+0

謝謝。而不是作業:我正在使用F#編寫一些我用C編寫的東西來熟悉函數式編程。 – AruniRC

+0

您能否詳細說明MoveNext()的位置?內部循環在'while'行中有MoveNext() – AruniRC

+0

我不知道該如何說清楚。在調用iter02.MoveNext()之前,您正在訪問iter02.Current。您必須先調用MoveNext()。 – Brian

3

您需要更改

let _,_,time01 = iter01.Current 
let _,_,time02 = iter02.Current 

let time01 = iter01.Current 
let time02 = iter02.Current 

使代碼與seq<int>類型檢查。

我不明白你的意圖。如果你想要到對應的每個元素對比較兩個序列,有更多功能的解決方案:

let mergeSeq seq01 seq02 = 
    Seq.map2 (fun s1 s2 -> if s2 < s1 then "2" else "1") seq01 seq02 

如果要合併兩個已排序的序列,使用GetEnumerator是不錯,但回國"2""1"沒有意義對我來說。

+0

有一些文件I/O涉及,以及相當大的數據塊和時間戳。希望保持「1」,「2」作爲從最後(下一個)合併步驟(未示出)讀取哪個序列的指示符。 – AruniRC

+0

'seq {}'是懶惰的,它建立了計算,而不是數據,所以你不應該擔心。也許你應該描述你的真實用例。 – pad

2

你寫的代碼,就好像

a={1,1,1;2,2,2;3,3,3...} 

只使用

  let time01 = iter01.Current 
      let time02 = iter02.Current 
+0

謝謝。立即解決問題,但在運行時仍然出現錯誤。問題已經過適當編輯。 – AruniRC