F#在从记录列表派生的Map上应用Map.filter

时间:2017-11-15 14:35:04

标签: f#

我有这些记录:

type Name        = string
type PhoneNumber = int
type Sex         = Male | Female
type YearOfBirth = int
type Interests   = string list
type Client      = {name: Name; phone: PhoneNumber; sex: Sex; birth: YearOfBirth; interests: Interests}

let client1 = {name = "Jon"; phone = 37613498; sex = Male; birth = 1980; interests = ["Cars"; "Boats"; "Airplanes"]}
let client2 = {name = "Jonna"; phone = 31852654; sex = Female; birth = 1970; interests = ["Makeup"; "Sewing"; "Bananas"]}

我将其列入名单:

let file1 = [client1;client2]

然后我尝试使用Map创建一个函数,该函数应该能够过滤file1并且只返回客户端,该客户端与该函数中给出的生日具有相同的生日。

示例:

requestMap 1980

在这种情况下会返回map [("Jon", (37613498, Male, 1980, ["Cars"; "Boats"; "Airplanes"]))]

我偶然发现了一个功能,但我现在有点卡住了。

let requestMap yob =
    Map.ofList [for f in file1 do yield f.name,(f.phone,f.sex,f.birth,f.interests)] |>
    Map.filter (fun key value -> )

我无法弄清楚如何在当前地图birth中找到value?因为它现在是正确的,它隐藏在value内,目前是PhoneNumber * Sex * YearOfBirth * Interests元组。

任何提示?

3 个答案:

答案 0 :(得分:4)

要访问元组的元素,可以使用模式匹配:

Map.filter (fun key (phone, sex, birth, interests) -> birth = yob)

或者,如果您对除了出生年份以外的任何事情不感兴趣,您可以使用下划线忽略所有其他字段:

Map.filter (fun _ (_, _, birth, _) -> birth = yob)

那就是说,我建议先过滤并在之后创建地图,这样会更便宜:

let requestMap yob = 
    file1 
    |> List.filter (fun x -> x.birth = yob)
    |> List.map (fun f -> f.name,(f.phone,f.sex,f.birth,f.interests))
    |> Map.ofList

虽然我们讨论的主题是:你为什么要首先创造那个巨大的元组?你不能让原始记录成为地图中的值吗?像这样:

let requestMap yob = 
    file1 
    |> List.filter (fun x -> x.birth = yob)
    |> List.map (fun f -> f.name, f)
    |> Map.ofList

答案 1 :(得分:3)

以下是其他答案中未提及的更多选项:

将整个Client存储在地图值中:

[for f in file1 do yield f.name, f]
|> Map.ofList
|> Map.filter (fun _ f -> f.birth = yob)

使用yield

执行条件if
[ for f in file1 do
    if f.birth = yob then
        yield f.name, f ]
|> Map.ofList

答案 2 :(得分:1)

我认为最好在将file1列表转换为地图之前对其进行过滤,而不是创建地图然后对其进行过滤。

let requestMap yob =
let filtered =
    List.filter (fun client ->
      match client with
      | { Client.birth = year } when year = yob -> true
      | _ -> false) file1
Map.ofList [for f in filtered do yield f.name,(f.phone,f.sex,f.birth,f.interests)]