简体   繁体   中英

Write a sequence of tuples to a csv file f#

Iam trying to write a sequence of tuples to a csv, but the normal File.WriteAllLines is overloaded by a sequence of tuples.

I have tried therefore to flatten my tuples into a sequence of strings.

Here is my code:-

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);;

When I use "tupleToString" on just one tuple the results are just fine.

However the Seq.collect part of allIsStrings returns the tuples broken down by characters.

I have also tried Seq.choose and Seq.fold, but these simply throw errors.

Can anyone advise as to what function from the sequence module I should be using - or advise on an alternative to File.WriteAllLines that would work on a tuple?

You need to use Seq.map to convert all elements of a list to string and then Array.ofSeq to get an array which you can pass to WriteAllLines :

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

Also, in your tupleToString function, you do not need to use reflection to check that the argument is a tuple. It will always be a tuple, because this is guaranteed by the type system. So you can just write:

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

You could use reflection if you wanted to make this work for tuples with arbitrary number of parameters (but that is a more advanced topic). The following gets elements of the tuple, converts them all to string and then concatenates them using a comma:

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())

The accepted answer is much better, but I've written this now, so there.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM