首页 > 代码库 > 12.3.3.1 序列表达式中的平面映射
12.3.3.1 序列表达式中的平面映射
12.3.3.1 序列表达式中的平面映射
假设我们有一个关于城市的元组列表,每个元组包含城市的名字和它所在的国家,另外,我们还有一个列表,是用户所选的城市。因此,我们可以这样表示样本数据:
let cities = [ ("New York","USA"); ("London", "UK");
("Cambridge","UK"); ("Cambridge", "USA") ]
let entered = [ "London";"Cambridge" ]
现在,假设我们要找出选定城市的国家。我们可以在 cities 列表中遍历所选的城市,找到国家。你可能可能已经看出了这种方法的问题了:有一个名为 Cambridge 的城市,在英国和美国都有,因此,对于一个城市,需要能够返回多条记录。在清单 12.10 中可以看到,我们在序列表达式中使用两个嵌套的 for 循环。
清单12.10 使用序列表达式联接集合 (F# Interactive)
> seq { for name in entered do [1]
for (n, c) in cities do [2]
if (n = name) then | [3]
yield sprintf "%s(%s)" n c };; |
val it : seq<string> = | 返回剑桥的
seq [ "London (UK)";"Cambridge (UK)"; "Cambridge (USA)" ] | 两个国家
外层的 for 循环遍历 entered 中的名字[1],嵌套的循环遍历 cities 列表[2]。这样,在嵌套的循环体内部,我们就可以比较每个输入城市的名字,是否与每个已知城市的名字相等。如果名字相同的话,嵌套在两个循环内的代码[3]使用 yield 语句,生成一个项目;如果名字不一样,就不产生任何元素。
用数据库术语来说,这个操作可以用联接(jion)来解释。输入名字的列表与包含城市信息的列表,使用城市名字作为键,进行联接。使用序列表达式来写这个代码是很容易的,它是 F# 中联接编程的首选方式。
我们提到过,任何序列表达式可以写成使用平面映射的操作,因此,我们可以看一下如何显式使用 Seq.collect 重写前面的示例。实际你不会这样做,但是,当我们研究类似于可选工作流,定义自己的、序列表达式时,这将是非常宝贵的。
12.3.3.1 序列表达式中的平面映射