2

我试图将一个元组序列写入 csv,但正常的 File.WriteAllLines 被一个元组序列重载。

因此,我试图将我的元组扁平化为一系列字符串。

这是我的代码:-

open System;;
open Microsoft.FSharp.Reflection;;

let tupleToString (t: string * float) = 
        if FSharpType.IsTuple(t.GetType()) 
        then String.Format("{0},{1}", fst t, snd t)
        else "";;

    let testTuple = ("monkey", 15.168);;

    tupleToString(testTuple);;

let testSeqTuple = [("monkey", 15.168); ("donkey", 12.980)];;

let allIsStrings (t:seq<string * float>) = Seq.collect tupleToString t;;

allIsStrings(testSeqTuple);;

当我只在一个元组上使用“tupleToString”时,结果就很好了。

然而, allIsStrings 的 Seq.collect 部分返回按字符分解的元组。

我也尝试过 Seq.choose 和 Seq.fold,但这些只会抛出错误。

任何人都可以建议我应该使用序列模块中的什么功能 - 或者建议可以在元组上工作的 File.WriteAllLines 的替代方法吗?

4

2 回答 2

10

您需要使用Seq.map将列表的所有元素转换为string然后Array.ofSeq获取可以传递给的数组WriteAllLines

let allIsStrings (t:seq<string * float>) = 
  t |> Seq.map tupleToString
    |> Array.ofSeq

此外,在您的tupleToString函数中,您不需要使用反射来检查参数是否为元组。它总是一个元组,因为这是由类型系统保证的。所以你可以写:

let tupleToString (t: string * float) = 
  String.Format("{0},{1}", fst t, snd t)      

如果您想对具有任意数量参数的元组进行这项工作,您可以使用反射(但这是一个更高级的主题)。以下获取元组的元素,将它们全部转换为字符串,然后使用逗号连接它们:

let tupleToString t = 
  if FSharpType.IsTuple(t.GetType()) then
    FSharpValue.GetTupleFields(t)
    |> Array.map string
    |> String.concat ", "
  else failwith "not a tuple!"

// This works with tuples that have any number of elements
tupleToString (1,2,"hi")
tupleToString (1.14,2.24)

// But you can also call it with non-tuple and it fails
tupleToString (new System.Random())
于 2012-10-25T15:33:30.630 回答
5

接受的答案要好得多,但我现在已经写了这个,所以在那里。

let testSeqTuple = [("monkey", 15.168); ("donkey", 12.980)]

let tupleToString t = String.Format("{0},{1}", fst t, snd t)
let tuplesToStrings t = Array.ofSeq (Seq.map tupleToString t)

for s in tuplesToStrings(testSeqTuple) do
    printfn "s=#%s" s
于 2012-10-25T15:49:24.287 回答