我有这些记录:
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
元组。
任何提示?
答案 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)]