引用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 的计算不会引起任何副作用。
注意:对于不同的运行可能会返回不同的结果,除非对基础集合类型进行了排序。
在查看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)
这就是我想出的,这不是一个很好的答案,因为它需要你急切地迭代第一个答案,所以如果你返回 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)
| 归档时间: |
|
| 查看次数: |
197 次 |
| 最近记录: |