Error in merging two sequences of timestamps to yield strings
-
16-06-2021 - |
Вопрос
The code sorts two input sequences - seq01 and seq02 - on the basis of their timestamp
values and returns a sequence that denotes which sequence is to be read for the values to be in order.
For cases where seq02's timestamp value is lesser than seq01's timestamp value we yield a "2" to the sequence being returned, else a "1". These denote whether at that point seq01 is to be taken or seq02 is to be taken for the data to be in order (by timestamp value).
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"
}
To test it in the FSI created two sequences a and b, a={1;3;5;...} and b={0;2;4;...}. So the expected values for let c = mergeSeq a b
would have been {"2","1","2","1"...}. However I am getting this error: error FS0001: The type ''a * 'b * 'c' does not match the type 'int'
EDIT
After correcting:
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"
}
After running this, there's another error: call MoveNext
. Somehow the iteration is not being performed.
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"
}
Решение
After the edit...
You need to call MoveNext on 2 before accessing current. You're not updating time02 as you move through 2 in the inner loop. And you're not checking for the end of sequences properly (e.g. if 2 ends but 1 is going, you'll try to access 2 after the end).
(Is this homework?)
Другие советы
You need to change
let _,_,time01 = iter01.Current
let _,_,time02 = iter02.Current
to
let time01 = iter01.Current
let time02 = iter02.Current
so that the code is type-checked with seq<int>
.
I don't understand your intention. If you want to compare each corresponding pair of elements in two sequences, there are more functional solutions:
let mergeSeq seq01 seq02 =
Seq.map2 (fun s1 s2 -> if s2 < s1 then "2" else "1") seq01 seq02
If you want to merge two sorted sequences, using GetEnumerator
is fine but returning "2"
and "1"
doesn't make sense to me.
You have written code as if
a={1,1,1;2,2,2;3,3,3...}
just use
let time01 = iter01.Current
let time02 = iter02.Current