【问题标题】:Write a sequence of tuples to a csv file f#将元组序列写入 csv 文件 f#
【发布时间】:2012-10-25 15:27:10
【问题描述】:

我正在尝试将元组序列写入 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 的替代方法?

【问题讨论】:

    标签: f# tuples export-to-csv


    【解决方案1】:

    您需要使用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())
    

    【讨论】:

    • 太棒了。比涂了油的闪电还快。
    • 感谢您提供的信息,是的,我确实输入过多。
    • 哇,添加了很多额外的信息。你应该得到额外的荣誉 :) 随着元组开始包含更多信息和类型,更高级的位将在稍后派上用场。
    • File.WriteAllLines 有一个需要seq&lt;string&gt; 的重载,因此Array.ofSeq 不是绝对必要的。
    • @ildjarn 好点!我猜它是在 .NET 2.0 或类似的版本之后添加的?
    【解决方案2】:

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

    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
    

    【讨论】:

    • 我会支持你,伙计。在速度和好的答案方面很难与 Tomas 竞争 :-)
    猜你喜欢
    • 1970-01-01
    • 2016-07-25
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    相关资源
    最近更新 更多