Reputation: 2277
I have this function that writes to an csv file. the output of the csv file should be like this.
title(string) body(string) images(list) variations(list)
ipsum1 lorem1 img1 variation1
empty empty img2 variation2
empty empty img3 variation3
The function I'm trying to use is something like this.
let col1 = ["title"; title]
let col2 = ["body"; stringedBody]
let col3 = ["images", images] //LIST
let col4 = ["allVariations",allVariations] //LIST
let cols = [col1; col2; col3; col4; ] //*col3 & 4 gives all elements must be of the same type as the first element, witch here is 'string' . This element has type 'string * string list*'
let transpose(xs: string list list) : string list list =
[0 .. xs.[0].Length - 1] |> List.map (fun i ->
xs |> List.rev |> List.fold (fun acc col -> col.[i] :: acc) []
)
let stringify_rows(xs: string list list) : string list =
xs |> List.map (fun row -> System.String.Join(";", row))
System.IO.File.WriteAllLines("\\test.csv", cols |> transpose |> stringify_rows)
But the problem seems to be with column 3 and 4, I have also tried to create an array of the images
let mutable img = [|images|]
but that gave me an similar error.
Thanks in advance.
Upvotes: 0
Views: 39
Reputation: 243041
If you want to process a list of things in F# in a uniform way, then all the things in your list need to be of the same type. This is not the case in your example. You use a list of strings in some cases (when you have different values for each row) but just a single string in other cases (when there is the same value for all rows).
The best way to fix your logic is to come up with a uniform representation. I think the easiest option is to use a list of string option
values. Then you can use Some "str"
for a value and None
for a missing value:
let col1 = [Some "title"; Some "lorem"; None; None]
let col2 = [Some "body"; Some "ipsum"; None; None]
let col3 = [Some "images"; Some "img1"; Some "img2"; Some "img3"]
let col4 = [Some "allVariations"; Some "var1"; Some "var2"; Some "var3"]
With this, most of your code (almost) works! The only change is that you need to make transpose
compatible with string option
. You can do that by changing the annotation to 'a list list
:
let transpose(xs: 'a list list) : 'a list list =
[0 .. xs.[0].Length - 1] |> List.map (fun i ->
xs |> List.rev |> List.fold (fun acc col -> col.[i] :: acc) []
)
I also changed stringify_rows
to add an empty string as the default value for missing values:
let stringify_rows(xs: string option list list) : string list =
xs |> List.map (fun row ->
row |> List.map (Option.defaultValue "") |> String.concat ";")
Upvotes: 1