Когда вы используете последовательности, любая ленивая функция добавляет некоторые издержки на последовательность.Вызов Seq.skip тысячи раз для одной и той же последовательности будет явно медленным.
Вы можете использовать Seq.zip
или Seq.map2
для обработки двух последовательностей одновременно:
> Seq.map2 (+) [1..3] [10..12];;
val it : seq<int> = seq [11; 13; 15]
Еслимодуля Seq недостаточно, вам может потребоваться написать собственную функцию.Я не уверен, что понимаю, что вы пытаетесь сделать, но эта функция-пример может вам помочь:
let fct (s1: seq<_>) (s2: seq<_>) =
use e1 = s1.GetEnumerator()
use e2 = s2.GetEnumerator()
let rec walk () =
// do some stuff with the element of both sequences
printfn "%d %d" e1.Current e2.Current
if cond1 then // move in both sequences
if e1.MoveNext() && e2.MoveNext() then walk ()
else () // end of a sequence
elif cond2 then // move to the next element of s1
if e1.MoveNext() then walk()
else () // end of s1
elif cond3 then // move to the next element of s2
if e2.MoveNext() then walk ()
else () // end of s2
// we need at least one element in each sequence
if e1.MoveNext() && e2.MoveNext() then walk()
Редактировать:
Предыдущая функция предназначаласьрасширить функциональность модуля Seq, и вы, вероятно, захотите сделать его функцией высокого порядка.Как сказал ildjarn, использование LazyList может привести к более чистому коду:
let rec merge (l1: LazyList<_>) (l2: LazyList<_>) =
match l1, l2 with
| LazyList.Cons(h1, t1), LazyList.Cons(h2, t2) ->
if h1 <= h2 then LazyList.cons h1 (merge t1 l2)
else LazyList.cons h2 (merge l1 t2)
| LazyList.Nil, l2 -> l2
| _ -> l1
merge (LazyList.ofSeq [1; 4; 5; 7]) (LazyList.ofSeq [1; 2; 3; 6; 8; 9])
Но я все же думаю, что вам следует отделить итерацию ваших данных от обработки.Написание функции высокого порядка для итерации - хорошая идея (в конце концов, не раздражает, если код функции итератора использует изменяемые перечислители).