什么是 Scala 的 Seq.Span 在 F# 中的等价物?

Aar*_*ack 5 .net f# scala

引用Scala 的文档

def span(p: (A) => Boolean): (Seq[A], Seq[A])
Run Code Online (Sandbox Code Playgroud)

根据谓词将此可迭代集合拆分为前缀/后缀对。

注意:c span p 等价于(但可能比)(c takeWhile p, c dropWhile p)等价,前提是谓词 p 的计算不会引起任何副作用。

注意:对于不同的运行可能会返回不同的结果,除非对基础集合类型进行了排序。

  • p - 测试谓词
  • 返回 - 由这个可迭代集合的最长前缀组成的一对,其元素都满足 p,以及这个可迭代集合的其余部分。
  • 定义类 - IterableOps ?可迭代的OnceOps
  • 注意 - 重用:调用此方法后,应丢弃调用它的迭代器,只使用返回的迭代器。使用旧迭代器是未定义的,可能会发生变化,并且也可能导致对新迭代器的更改。

在查看Seq的F# 文档时,我没有看到任何等效内容。

groupBy、partition、splitAt,它们都不符合我想要做的。这就像同时执行 takeWhile 和 skipWhile,但不需要两次迭代,您只需要一个函数将返回 (takeWhile, skipWhile) 元组的迭代。

输出应与以下函数匹配

module List
let span (predicate: 'a -> bool) (list: 'a list): ('a list * 'a list) =
    (list |> List.takeWhile predicate, list |> List.skipWhile predicate)
Run Code Online (Sandbox Code Playgroud)

但只需要一次迭代,因为我的序列可能是无限的。

[1;2;3;4] |> List.span (fun i -> i % 2 = 1) => ([1], [2;3;4])
Run Code Online (Sandbox Code Playgroud)

Aar*_*ack 1

这就是我想出的,这不是一个很好的答案,因为它需要你急切地迭代第一个答案,所以如果你返回 true 足够长的时间,你就会在没有记忆的情况下崩溃。我会将这个问题再留待几天,如果我没有看到更好的答案,我会标记这个答案。再次,我真的很想要一个更好的答案,在任何情况下都可以完全适用于无限序列。

module Seq

let span (predicate: 'a -> bool) (sequence: 'a seq): ('a seq * 'a seq) =
    let enumerator = sequence.GetEnumerator()
    let isNotDone = ref (enumerator.MoveNext())
    let first = seq {
        let e = enumerator
        if !isNotDone then
            while (!isNotDone && predicate e.Current) do
                yield enumerator.Current
                isNotDone := e.MoveNext() }
    let second = seq {
        use e = enumerator
        if !isNotDone then
            yield e.Current
            while e.MoveNext() do
                yield e.Current }
    let eagerFirst = List.toSeq (Seq.toList first)
    (eagerFirst, second)
Run Code Online (Sandbox Code Playgroud)