当您使用序列时,任何惰性函数都会在序列上增加一些开销。在同一序列上调用 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])
但是我仍然认为您应该将数据的迭代与处理分开。编写一个高阶函数进行迭代是一个好主意(最后,如果迭代器函数代码使用可变枚举器,这并不烦人)。