F# 合并两个记录列表并计算结果
我有以下两种类型的记录列表:F# 合并两个记录列表并计算结果,f#,F#,我有以下两种类型的记录列表: type AverageTempType = {Date: System.DateTime; Year: int64; Month: int64; AverageTemp: float} type DailyTempType = {Date: System.DateTime; Year: int64; Month: int64; Day: int64; DailyTemp: float} 我想得到一个新的列表,它由DailyTestType和AverageTest
type AverageTempType = {Date: System.DateTime; Year: int64; Month: int64; AverageTemp: float}
type DailyTempType = {Date: System.DateTime; Year: int64; Month: int64; Day: int64; DailyTemp: float}
我想得到一个新的列表,它由DailyTestType和AverageTestType组成。不过,对于每一条每日记录,我希望得到匹配月份的每日温度-平均温度
我想我可以使用如下所示的循环,并将其按摩成合理的输出:
let MatchLoop =
for i in DailyData do
for j in AverageData do
if (i.Year = j.Year && i.Month = j.Month)
then printfn "%A %A %A %A %A" i.Year i.Month i.Day i.DailyTemp j.Average
else printfn "NOMATCH"
我也尝试过通过匹配来实现这一点,但我不能完全做到(我不确定如何在输入类型中正确定义列表,然后迭代以获得结果。我也不确定这种方法是否有意义):
我已经研究过Deedle,我认为它可以相对容易地做到这一点,但我渴望了解如何在较低的级别上做到这一点。我会将first AverageTestType seq转换为Map(降低连接成本): 然后,您可以加入并返回一个选项,以便使用代码可以执行任何您想要的操作(打印、存储、错误等):
您可以做的是创建月平均数据的地图。您可以将地图视为只读词典:
let averageDataMap =
averageData
|> Seq.map (fun x -> ((x.Year, x.Month), x))
|> Map.ofSeq
这个特定的映射是一个映射
,用更简单的话来说,这意味着映射中的键是年和月的元组,与每个键相关联的值是一个平均类型
记录
这使您能够根据每日数据查找所有匹配的月份数据:
let matches =
dailyData
|> Seq.map (fun x -> (x, averageDataMap |> Map.tryFind (x.Year, x.Month)))
这里,matches的数据类型为seq
。同样,简单地说,这是一个元组序列,其中每个元组的第一个元素是原始的每日观察值,第二个元素是相应的月平均值(如果找到匹配项),或者None
如果没有找到匹配的月平均值
如果要打印OP中的值,可以执行以下操作:
matches
|> Seq.map snd
|> Seq.map (function | Some _ -> "Match" | None -> "No match")
|> Seq.iter (printfn "%s")
此表达式以匹配的
开头;然后取出每个元组的第二个元素;然后再次将Some
值映射到字符串“Match”,将None
值映射到字符串“No Match”;最后打印每个字符串。列表是否已排序?如果你想在较低的级别上做一些事情,这一点很重要。我可以让他们按照我想匹配的键进行排序。@Fusi123你总是可以使用,或者只是研究它是如何实现的,以及它如何提供与左外连接等效的功能。
…)谢谢,马克,这很好用。你能解释一下(或者可能是一个参考资料)如何正确处理期权类型吗?如果我使用Map.find,我可以使用matches |>Seq.Map(fun(x,y)->x.DailyTemp,x.DailyTemp-y.AvgTemp)|>printfn“%A”
选项类型记录在这里:另一个值得一读的好方法是:谢谢马克,我看了这些例子。尽管如此,我仍然有点挣扎,因为所有的例子似乎都是琐碎的案例。我看不到有一系列选项的情况,我也无法更改您的示例,因为我无法“访问”原始元组。我可能会发布另一个问题。
let averageDataMap =
averageData
|> Seq.map (fun x -> ((x.Year, x.Month), x))
|> Map.ofSeq
let matches =
dailyData
|> Seq.map (fun x -> (x, averageDataMap |> Map.tryFind (x.Year, x.Month)))
matches
|> Seq.map snd
|> Seq.map (function | Some _ -> "Match" | None -> "No match")
|> Seq.iter (printfn "%s")