简体   繁体   中英

F# - CSV to two keys dictionary

I have localization CSV file with following structure

Key, Language1, Language2, Language3
some key, translation1, translation2, translation3

I'd like to write function that return multidimensional array from what I can easy get translation. Eg

translations["some key"]["Language1"] returns me "translation1"

I wrote only loading of file

open GleedsSnags.Localization
open FSharp.Data

type Loc = CsvProvider<"Localization.csv">
let locData = Loc.Load("Localization.csv")

but I don't know what data structure is best for this issue and how to construct result in F# in most elegant way. Then I'd like to read this structure in C#.

Any idea?

Using type providers you can achieve the following easily:

open FSharp.Data

type Loc = CsvProvider<"Localization.csv">

let myMap = Loc.Rows |> Seq.map (fun r -> r.Key, r) |> Map.ofSeq

// accessing translations:
let trans1 = myMap.["some key"].Language1
let trans2 = myMap.["some key"].Language2

Here the type of each row in the map is generated by the type provider and it may cause trouble when passing the result around between different libraries.

On the other hand, there is also another tool for dealing with CSV files in the FSharp.Data module, namely CsvFile :

open FSharp.Data

let csv = CsvFile.Load("Localization.csv")
// To use the dynamic operator '?'
open FSharp.Data.CsvExtensions
// For Dictionary
open System.Collections.Generic

let myMap2 = csv.Rows |> Seq.map (fun r -> r?Key, r) |> Map.ofSeq 
let dict  = Dictionary(myMap2)

Now you have a dictionary of type Dictionary<string,CsvRow> that can be accessed as follows:

dict.["some key"].["Language1"]

First of all: https://msdn.microsoft.com/en-us/library/h6270d0z(v=vs.110).aspx

If you need to do it this way, you have your files and may possibly do something like:

let translation key language = 
 let d = 
  locData
  |> Seq.filter(fun x -> x.Key = key)
  |> Seq.exactlyone
 d.[language]

To speed stuff up, use some Map or something:

let mapLocData = 
 locData 
 |> Seq.groupBy (fun x -> x.Key)
 |> Map.ofSeq

let translation key language = 
  mapLocData.[key].[language]

...ish...

code not at all tested, and only written here etc.

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