dictionary - F# 类型匹配 - 无法创建映射或匹配记录

标签 dictionary types f# pattern-matching

我尝试修改 WikiBooks 示例以接受 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."

关于dictionary - F# 类型匹配 - 无法创建映射或匹配记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50394438/

相关文章:

python - 更新字典列表中的列表值

c++ - C++中python dict和tr1::unordered_map的区别

python - 使用过滤器和映射在 python 中查找扩展名为 .txt 和 .py 的目录中的所有文件

arrays - 在 TypeScript 中描述一个深度嵌套的数组

.net - 为什么运行时将泛型类型显示为 "GenericType` n"?

f# - 将 app.config 中的连接字符串与 FSharp.Data.SqlClient 结合使用

java - 如何在 HashMap 中保存枚举类?

c++ - 类和类型的问题

haskell - F# 相当于 Haskell scanl/scanr

f# - 在 FAKE (F# Make) 中发布网站