LINQ学习笔记:选取Select(4)
http://www.itjxue.com 2015-07-17 01:59 来源:未知 点击次数:
外部迭代变量
在我们前面的例子中,fullName在SelectMany之后变成了一个外部迭代变量. 这个外部迭代变量依然在可用范围内直到查询结束或者到达一个into从句:
1: IEnumerable<string> query =
2:
3: from fullName in fullNames // 外部变量
4:
5: from name in fullName.Split( ) // 迭代变量
6:
7: select name + ” came from “ + fullName;
8:
9: Anne came from Anne Williams
10:
11: Williams came from Anne Williams
12:
13: John came from John Fred Smith
如果要使用Lambda语法的话,尤其在有where或者orderby的情况下,会更加复杂一点,这里有一个技巧:
1: from fullName in fullNames
2:
3: from x in
4:
5: fullName.Split( )
6:
7: .Select (name => new { name, fullName } )
8:
9: orderby x.fullName, x.name
10:
11: select x.name + ” came from “ + x.fullName;
我们使用了一个匿名类型来搭载临时数据,类似let从句的作用.最后我们可以得到一个完整的Lambda语法的查询:
1: IEnumerable<string> query = fullNames
2:
3: .SelectMany (fName =>
4:
5: fName.Split( )
6:
7: .Select (name => new { name, fName } ))
8:
9: .OrderBy (x => x.fName)
10:
11: .ThenBy (x => x.name)
12:
13: .Select (x => x.name + ” came from “ + x.fName);
复合查询的思考
正如我们前面看到的例子,如果我们需要外部迭代变量, 那么使用复合语法是一个很好的选择,因为它的语义让你可以更加直观的思考.
编写额外的生成器主要有两个基础的模式, 第一个是扩展和平整结果,为了做到这一点,我们可以通过调用已有查询变量的属性或者方法来完成,上面的例子我们就使用了这个方法.
在LINQ to SQL中一个类似的查询就是当你扩展关联的子属性,以下的实例列出了所有的客户和他们对应的采购单:
1: IEnumerable<string> query =
2:
3: from c in dataContext.Customers
4:
5: from p in c.Purchases
6:
7: select c.Name + ” bought a “ + p.Description;
8:
9: Tom bought a Bike
10:
11: Tom bought a Holiday
12:
13: Dick bought a Phone
14:
15: Harry bought a Car
另外一个模式就是执行一个交叉连接,为了做到这一点, 我们的selector表达式返回的将会是一个序列而不是一个迭代变量了:
1: int[] numbers = { 1, 2, 3 };
2:
3: string[] letters = { “a”, “b” };
4:
5: IEnumerable<string> query = from n in numbers
6:
7: from l in letters
8:
9: select n.ToString( ) + l;
10:
11: RESULT: { “1a”, “1b”, “2a”, “2b”, “3a”, “3b” }
这种风格的查询就是SelectMany风格关联的基础.
使用SelectMany做关联
我们可以使用SelectMany,并通过过滤一个交叉结果集来关联两个序列.例如, 假设我们要安排一场比赛的选手对决, 我们使用以下的查询:
1: string[] players = { “Tom”, “Jay”, “Mary” };
2:
3: IEnumerable<string> query =
4:
5: from name1 in players
6:
7: from name2 in players
8:
9: select name1 + ” vs “ + name2;
10:
11: RESULT: {“Tom vs Tom”, “Tom vs Jay”, “Tom vs Mary”,
12:
13: “Jay vs Tom”, “Jay vs Jay”, “Jay vs Mary”,
14:
15: “Mary vs Tom”, “Mary vs Jay”, “Mary vs Mary”}
但这并非我们期望的结果,很明显,选手自己并不需要与自己比赛,因此我们必须要过滤这些不符合条件的输出元素:
1: IEnumerable<string> query =
2:
3: from name1 in players
4:
5: from name2 in players
6:
7: where name1.CompareTo (name2) > 0
8:
9: orderby name1, name2
10:
11: select name1 + ” vs “ + name2;
12:
13: RESULT: { “Jay vs Mary”, “Jay vs Tom”, “Mary vs Tom” }
此过滤断言构成了连接条件,我们的查询可以被称为非等连接,因为连接条件没有使用等式操作符.
(责任编辑:IT教学网)
上一篇:LINQ学习笔记:聚合方法
下一篇:LINQ学习笔记:创建方法