我试图改编一个维基教科书示例以接受csv输入和类型,但我正在努力将传入的类型列表转换为字典并匹配用户输入。
// https://en.wikibooks.org/wiki/F_Sharp_Programming/Sets_and_Maps#Examples_2
module SOQN =
open System
open FSharp.Data
type Country = Country of string
type City = City of string
type CountryCapital = {
Country:Country
City:City
}
let [<Literal>] sampleCsv = @"D:Country_Capitals.csv"
type Capitals = CsvProvider<sampleCsv, Separators=",", HasHeaders=true>
let readFromCsvFile (fileName:string) =
let data = Capitals.Load(fileName)
[ for row in data.Rows do
yield { Country = Country row.Country; City = City row.City; } ]
let countryCapitals =
readFromCsvFile sampleCsv
// -> |> Map.ofList
Console.Write("Find capital by country (type 'q' to quit): ")
match Console.ReadLine() with
| "q" -> Console.WriteLine("Bye!")
| country ->
match countryCapitals with
// -> | { Country = country } -> Console.WriteLine("Capital of {0} is {1}n", country, capital)
| _ -> Console.WriteLine("Country not found.n")
// Expected Output: Find capital by country (type 'q' to quit): Egypt
// Capital of Egypt is Cairo
我错过了什么?
您需要使用元组从List
创建Map
,因此您根本不需要记录类型。 然后,您需要匹配输入国家/地区的Map.tryFind
。 下面是一个使用元组和Map.tryFind
的示例。 我所做的其他更改是使用printfn
而不是Console.WriteLine
并简化列表生成表达式:
open System
open FSharp.Data
let [<Literal>] sampleCsv = @"D:Country_Capitals.csv"
type Capitals = CsvProvider<sampleCsv, Separators=",", HasHeaders=true>
let readFromCsvFile (fileName:string) =
let data = Capitals.Load(fileName)
[ for row in data.Rows -> (row.Country, row.City) ]
let countryCapitals =
readFromCsvFile sampleCsv
|> Map.ofList
printfn "Find capital by country (type 'q' to quit): "
match Console.ReadLine() with
| "q" -> printfn "Bye!"
| country ->
match countryCapitals |> Map.tryFind country with
| Some capital -> printfn "Capital of %s is %s" country capital
| _ -> printfn "Country not found."
编辑要显示记录类型的继续使用,请执行以下操作:
open System
open FSharp.Data
type CountryCaptial = { Country: string; Capital: string }
let [<Literal>] sampleCsv = @"D:Country_Capitals.csv"
type Capitals = CsvProvider<sampleCsv, Separators=",", HasHeaders=true>
let readFromCsvFile (fileName:string) =
let data = Capitals.Load(fileName)
[ for row in data.Rows -> { Country = row.Country; Capital = row.City } ]
let countryCapitals =
readFromCsvFile sampleCsv
|> List.map (fun c -> c.Country, c)
|> Map.ofList
printfn "Find capital by country (type 'q' to quit): "
match Console.ReadLine() with
| "q" -> printfn "Bye!"
| country ->
match countryCapitals |> Map.tryFind country with
| Some countryCapital -> printfn "Capital of %s is %s" countryCapital.Country countryCapital.Capital
| _ -> printfn "Country not found."