12.3.3.3 在 C# 中使用平面映射

类似于 collect 函数的LINQ 运算符,是 SelectMany,但两者之间也有差异,因为 LINQ 有不同的要求。而 F# 序列表达式只能使用 collect 函数表示,LINQ 查询可以使用许多其它运算符,所以,对于序列操作,它们需要不同的方式。

我们再先看一下普通语法,然后,再考虑转换成使用显式扩展方法的语法,我们还使用前面的 F# 示例的数据。有关国家信息的城市列表中包含了 CityInfo 类的实例,有两个属性,输入名字的列表只包含字符串。清单 12.13 展示的是我们写的 LINQ 查询,查找输入城市所属的国家。

清单 12.13 使用查询找出输入城市的国家 (C#)

var q =

from e in entered     [1]

from known in cities     [2]

where known.City == e                                | [3]

select string.Format("{0} ({1})", known.City, known.Country);  |

这个查询表达式与我们在前面示例中所实现的完全相同,它遍历两个数据源(entered [1] 和 cities [2]),我们交叉联接两个集合,然后,只产生与用户输入城市名,在“已知的城市”列表中相对应的城市记录;最后,格式化输出[3]。

在 C# 查询表达式语法中,我们也可以使用 jion 子句,直接指定两个数据源的键(在我们的例子中,是值 e 和 known.City 值)。也有一些不同:join 子句可能更有效,但是,几个 from 子句更灵活。特别是,我们生成的第二个序列可能会根据我们当前看到的第一个序列中的项目。

正如我们刚才所说的,查询表达式可以转换为正常的成员调用。在查询表达式中,第一个 from 子句之后的任何 from 子句,都被转换成对 SelectMany 的调用。清单 12.14 显示了由 C# 编译器执行的转换。

清单 12.14 查询转换成运算符调用 (C#)

var q = entered

.SelectMany(

e=> cities,     [1]

(e, known) => new { e, known })     [2]

.Where(tmp => tmp.known.City == tmp.e)   |

.Select(tmp => String.Format("{0} ({1})",     | 筛选,格式化输出

tmp.known.City, tmp.known.Country));   |

不像在 F # 中,if 条件被嵌套在两个 for 循环中(平面映射),在 C# 中的操作是没有嵌套的顺序组合。首先是 SelectMany 运算符,实现联接;筛选和映射,在序列的末尾用 Where 和 Select 执行。

第一个 lambda 函数[1],为源列表中的每个项目生成指定集合,这个参数对应于提供给 F# 的 collect 函数的参数值的函数。在查询中,返回所有已知的城市,所以,操作只执行联接,而没有任何筛选,或进一步地处理。第二个参数[2]指定如何根据原始序列的中元素生成结果,由函数所返回的新生成的序列中的元素。在示例中,我们用包含了两个项目的匿名类型,这样,我们就可以在以后的查询运算符使用它们。

在 F# 中,所有的处理是在筛选和映射(filtering projection,外国人也能这样并列使用名字了,要么就应该是平面映射)内部做的,这样,我们只返回最终的结果。在 C# 中,大多数处理在后面完成,所以,我们需要返回两个元素,再组合成一个值(使用匿名类型),使它们能在以后访问。通常,第一个 from 子句指定主查询源,如果我们添加更多的 from 子句,它们通过 SelectMany 运算符,与原始的数据源联接。任何后续的运算符,比如,where 和 select,都只能加到最后,处理联接好的数据源。这不同于
F# 转换,因为在 F# 中,筛选和映射都嵌套在最里面,调用 Seq.collect。

理解如何转换并不是那么重要,但是,下一节我们还是要作一点了解。我们将会看到,F# 序列表达式表示更普通的想法,也可以在一定程度上使用 LINQ 查询来表示;我们已经看到的平面映射将发挥关键作用。

时间: 2024-10-05 08:09:09

12.3.3.3 在 C# 中使用平面映射的相关文章

12.3.3.1 序列表达式中的平面映射

假设我们有一个关于城市的元组列表,每个元组包含城市的名字和它所在的国家,另外,我们还有一个列表,是用户所选的城市.因此,我们可以这样表示样本数据: let cities = [ ("New York","USA"); ("London", "UK"); ("Cambridge","UK"); ("Cambridge", "USA") ] let e

SQL点滴12—SQL Server备份还原数据库中的小把戏

原文:SQL点滴12-SQL Server备份还原数据库中的小把戏 备份数据库时出现一个不太了解的错误 ,错误信息“is formatted to support  1 media families, but 2 media families are expected according to the backup device specification”.如下图: 解决办法是首先选中击上一次备份的文件,点击Remove,去掉当前的备份文件,然后再点击OK备份.这样才能正确的备份.也在微软帮助

Error:(12, 24) 警告: [deprecation] android.hardware中的Camera已过时.android

问题:android studio编译项目时出现: Error:(12, 24) 警告: [deprecation] android.hardware中的Camera已过时 解决:(只是让其不提示) 1.app的 build.gradle中 1 android { 2 ... 3 lintOptions { 4 checkReleaseBuilds false 5 abortOnError false 6 7 } 8 } 2.根目录的build.gradle中 allprojects { ...

1.6 字典中的键映射多个值

body, td { font-family: 微软雅黑; font-size: 10pt; } Edit 1.6 字典中的键映射多个值 问题 实现一个字典结构,一个键可以对应多个值 解决方案 1.列表和集合 1.>>> d2.{'b': [4, 5], 'a': [1, 2, 3]}3.>>> d['b']4.[4, 5]5.>>> e={'a':{1,2,2,3},'b':{2,3,4,4}}6.>>> e7.{'b': {2,

详解Java的MyBatis框架中SQL语句映射部分的编写

这篇文章主要介绍了Java的MyBatis框架中SQL语句映射部分的编写,文中分为resultMap和增删查改实现两个部分来讲解,需要的朋友可以参考下 1.resultMap SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: ? 1 2 3 4 5 6 <mappers>   <mapper resource="com/limi

12.3.3.2 直接使用平面映射

首先,我们要看看平面映射到底是什么样子.通常,理解函数如何运行的第一步,就是研究类型签名.图 12.2 比较了 Seq.map(普通映射)和 Seq.collect(平面映射)的类型签名. 图 12.2 对于每个输入元素,普通映射返回一个元素,而平面映射,可以返回元素的任意集合. 提醒一下,类型签名中的 # 号,描述映射函数,传递给 collect,表示函数的返回类型不必一定是 seq <'b> 类型.在前一章,我们讨论过使用 # 号的类型声明,#seq<'b> 位置上可以用实现了

12.3.3 平面映射(flattening projection)

12.3.3 平面映射(flatteningprojection) 平面映射,可以为源集合中的每个元素,生成元素序列,合并所有返回序列.我们很快就会看到,这是定义其他处理操作,包括映射和筛选,的基本操作.平面映射所独有的特征,就是能够为每个输入元素生成多个输出元素. 注意 在 LINQ 库中,这个操作称为 SelectMany.在查询表达式中,用多个 from 子句表示.从名字可以看出,它类似于 Select 操作,但是能够为源中的每个项目返回多个元素.F# 库中对应的函数是 Seq.colle

NX二次开发-UFUN将建模绝对空间中的点映射到工程图坐标UF_VIEW_map_model_to_drawing

1 #include <uf.h> 2 #include <uf_ui.h> 3 #include <uf_draw.h> 4 #include <uf_view.h> 5 #include <uf_curve.h> 6 7 8 UF_initialize(); 9 10 //在建模里创建点 11 double p1[3] = { 20, 20, 20 }; 12 tag_t p1_tag = NULL_TAG; 13 UF_CURVE_crea

VS2015--在 Visual Studio 中调试时映射调用堆栈上的方法

https://msdn.microsoft.com/zh-cn/library/dn194476.aspx 在 Visual Studio 中调试时映射调用堆栈上的方法 创建代码图,以便在调试时对调用堆栈进行可视化跟踪.你可以在图中进行标注以跟踪代码执行的操作,以便专注于查找 Bug. 生成调用堆栈图 1 开始调试.(键盘:"F5") 2 在你的应用进入中断模式或你单步执行某一函数之后,请选择"代码图".(键盘:Ctrl + Shift + `) 当前的调用堆栈在