我有一个包含两列文本和计数的 CSV 文件。目标是从这个转换文件:

some text once,1
some text twice,2
some text thrice,3

对此:
some text once,1
some text twice,1
some text twice,1
some text thrice,1
some text thrice,1
some text thrice,1

重复每行计数次数并将计数分布在那么多行上。

在我看来,这似乎是 Seq.unfold 的一个很好的候选者,在我们阅读文件时生成额外的行。我具有以下生成器功能:
let expandRows (text:string, number:int32) =
    if number = 0
    then None
    else
        let element = text                  // "element" will be in the generated sequence
        let nextState = (element, number-1) // threaded state replacing looping
        Some (element, nextState)

FSI 产生以下函数签名:
val expandRows : text:string * number:int32 -> (string * (string * int32)) option

在 FSI 中执行以下操作:
let expandedRows = Seq.unfold expandRows ("some text thrice", 3)

产生预期:
val it : seq<string> = seq ["some text thrice"; "some text thrice"; "some text thrice"]

问题是:如何将其插入更大的 ETL 管道的上下文中?例如:
File.ReadLines(inFile)
    |> Seq.map createTupleWithCount
    |> Seq.unfold expandRows // type mismatch here
    |> Seq.iter outFile.WriteLine

下面的错误发生在管道上下文中的 expandRows 上。
Type mismatch.
Expecting a 'seq<string * int32> -> ('a * seq<string * int32>) option'
but given a     'string * int32 -> (string * (string * int32)) option'
The type    'seq<string * int 32>' does not match the type 'string * int32'

我期待 expandRows 返回字符串的 seq,就像在我的独立测试中一样。由于这既不是“期望”也不是“给定”,我很困惑。有人可以指出我正确的方向吗?

代码的要点在这里:
https://gist.github.com/akucheck/e0ff316e516063e6db224ab116501498

最佳答案

Seq.map 产生一个序列,但 Seq.unfold 不接受一个序列,它接受一个单一的值。所以你不能直接将 Seq.map 的输出通过管道传输到 Seq.unfold 。你需要一个元素一个元素地做。

但是,对于每个元素,您的 Seq.unfold 将生成一个序列,因此最终结果将是一个序列序列。您可以使用 Seq.collect 在单个序列中收集所有这些“子序列”:

File.ReadLines(inFile)
    |> Seq.map createTupleWithCount
    |> Seq.collect (Seq.unfold expandRows)
    |> Seq.iter outFile.WriteLine
Seq.collect 接受一个函数和一个输入序列。对于输入序列的每个元素,该函数应该生成另一个序列,Seq.collect 会将所有这些序列连接成一个。您可能会将 Seq.collect 视为 Seq.mapSeq.concat 组合在一个函数中。此外,如果您来自 C#,那么 Seq.collect 在那里被称为 SelectMany

关于f# - 在 F# 中,如何在更大管道的上下文中使用 Seq.unfold?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41374343/

10-16 09:08