我们的目标是展示自 1990 年以来,不同地区森林面积的变化。我们需要遍历所有已有的地区,检查数据是否可用,找到下载的指标值。这可以通过使用我们创建的映射,非常轻松地完成,因为已经用年份和地区 ID 作为键。
但是需要小心,因为有一些数据可能会缺失,因此,我们要过滤掉所有年份没有数据的地区。另外,我们还想要显示森林总面积,而不是百分比,因此,在返回数据之前,要进行简单的计算。虽然听起来可能很难,但是,代码并不非常复杂。清单 13.17 显示了最终我们要在 F# Interactive 中输入的几条命令,能得到我们想要收集的数据。
清单 13.17 计算森林面积 (F# Interactive)
> let calculateForests(area:float<km^2>, forest:float<percent>) = <--[1] 计算森林总面积
let forestArea = forest * area
forestArea / 100.0<percent>
;;
val calculateForests : float<km ^ 2> * float<percent> -> float<km ^ 2>
> let years = [ 1990; 2000; 2005 ]
let dataAvailable(key) = <-- [2] 对于给定的给定的键,值是否可用?
years |> Seq.forall (fun y –>
(Map.contains (y, key) areas) &&
(Map.contains (y, key) forests));;
val years : int list
val dataAvailable : string –> bool
> let getForestData(key) = <-- [3] 得到每年的值
[| for y in years do
yield calculateForests(areas.[y, key], forests.[y, key]) |];;
val getForestData : string -> float<km ^ 2> array
> let stats = seq { <-- [4] 对所有地区,查找可用数据
for name in regions do
if dataAvailable(name) then
yield name, getForestData(name) };;
val stats : seq<string * float<km ^ 2> array>
清单 13.17 定义了几个辅助函数,处理下载的数据,并定义了一个名为 stats(统计数据)的值,包含最后结果。由于有了计量单位,可以很容易看出第一个函数做了什么[1],它用该地区的总面积和森林面积所占的百分比,计算森林总面积,以平方公里计。
第二个函数[2]检查我们所需要的数据,对于指定的地区 ID,和我们感兴趣的三年是否都可用。它使用函数 Map.contains,测试 F# 映射(由第二个参数描述)是否包含由第一个参数值指定的键。最后一个辅助函数[3]看起来和第二个很相似,它假定数据是可用的,使用年以及地区名作为键,对所有监控的年份,从映射中提取数据;然后,使用第一个函数,从原始数据计算出森林面积。
有了最后两个函数,我们就可以收集所有地区的统计数字了[4]。返回值是元组的序列,元组的第一个元素为地区名,第二个元素为数组。数组有三个元素,对应于所监控的三年的值。
在 F# Interactive 中获取数据以后,就可以观察,但是在互动窗口中,通过输出数据很难看到各种模式。为了能够从收集的数据中获取更多的信息,必须以更友好的方式,对数据进行可视化,例如,使用 Microsoft Excel。