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.