1,LINQ查询
var query = from r in Formula1.GetChampion() where r.Country == "Brazil" orderby r.Wins descending select r; foreach (var racer in query) { Console.WriteLine($"{racer:A}"); }
语法:查询表达式必须以from子句开头,以select活group子句结束。在这两个子句之间,可以使用where、orderby、join、let和其他from子句。
执行:如上,变量query只指定了LINQ查询。该查询不是通过这个赋值语句执行的,只要使用foreach循环访问查询,该查询就会执行。
var names = new List<string> {"Nino", "Alberto", "Juan"}; var namesWithJ = from n in names where n.StartsWith("J") orderby n select n; Console.WriteLine("First iteration:"); foreach (var n in namesWithJ) { Console.WriteLine(n); } names.AddRange(new []{ "John", "Jim", "Jason" }); Console.WriteLine("Second iteration:"); foreach (var n in namesWithJ) { Console.WriteLine(n); }
输出:
First iteration:
Juan
Second iteration:
Jason
Jim
John
Juan
但是如果用了ToArray()、ToList(),查询结果将保持不变。
var names = new List<string> {"Nino", "Alberto", "Juan"}; var namesWithJ = (from n in names where n.StartsWith("J") orderby n select n).ToList(); Console.WriteLine("First iteration:"); foreach (var n in namesWithJ) { Console.WriteLine(n); } names.AddRange(new []{ "John", "Jim", "Jason" }); Console.WriteLine("Second iteration:"); foreach (var n in namesWithJ) { Console.WriteLine(n); }
输出:
First iteration:
Juan
Second iteration:
Juan
2,复合的from语句
var farrariDrivers = from r in Formula1.GetChampion() from c in r.Cars where c == "Ferrari" orderby r.LastName select r.FirstName + " " + r.LastName; foreach (var r in farrariDrivers) { Console.WriteLine(r); }
3,Take扩展方法
获取查询结果前10条
var racers = (from r in Formula1.GetChampion() orderby r.Country, r.LastName, r.FirstName select r).Take(10);
4,分组
var countries = from r in Formula1.GetChampion() group r by r.Country into g orderby g.Count() descending, g.Key where g.Count() >= 2 select new { Country = g.Key, Count = g.Count() }; foreach (var item in countries) { Console.WriteLine($"{item.Country,-10} {item.Count}"); }
5,内连接
var racers = from r in Formula1.GetChampion() from y in r.Years select new { Year =y, Name = r.ToString() }; var teams = from t in Formula1.GetContructorChampions() from y in t.Years select new { Year = y, Name = t.Name }; var racersAndTeams = (from r in racers join t in teams on r.Year equals t.Year select new { r.Year, Champion = r.Name, Constructor = t.Name } ).Take(10); Console.WriteLine("Year World Champion\t Constructor Title"); foreach (var item in racersAndTeams) { Console.WriteLine($"{item.Year}:{item.Champion,-20} {item.Constructor}"); }
输出:
Year World Champion Constructor Title
1958:Mike Hawthorn Vanwall
1961:Phil Hill Ferrari
1964:John Surtees Ferrari
1963:Jim Clark Lotus
1965:Jim Clark Lotus
1959:Jack Brabham Cooper
1960:Jack Brabham Cooper
1966:Jack Brabham Brabham
1967:Denny Hulme Brabham
1962:Graham Hill BRM
6,左外链接
var racersAndTeams = (from r in racers join t in teams on r.Year equals t.Year into rt from t in rt.DefaultIfEmpty() select new { r.Year, Champion = r.Name, Constructor = t == null ?"no constructor championship":t.Name } ).Take(10);
红色的部分是和内连接不一样的地方
左外连接返回左边序列中的全部元素,即使他们在右边的序列中并没有匹配的元素。
7,集合操作
//定义一个委托保存LINQ查询 Func<string,IEnumerable<Racer>> racersByCar = car => from r in Formula1.GetChampion() from c in r.Cars where c == car orderby r.LastName select r; //用Intersect()扩展方法,获得驾驶法拉利和迈凯伦的所有冠军 Console.WriteLine("World champion with Ferrari and Mclaren:"); foreach (var racer in racersByCar("Ferrari").Intersect(racersByCar("McLaren"))) { Console.WriteLine(racer); }
输出:
World champion with Ferrari and Mclaren:
Niki Lauda
8,合并
var racerNames = from r in Formula1.GetChampion() where r.Country == "Italy" orderby r.Wins descending select new { Name = r.FirstName + " " + r.LastName }; var racerNamesAndStars = from r in Formula1.GetChampion() where r.Country == "Italy" orderby r.Wins descending select new { LastName = r.LastName, Starts = r.Starts }; //Zip()方法 var racers = racerNames.Zip(racerNamesAndStars, (first, second) => first.Name + ",starts:" + second.Starts); foreach (var racer in racers) { Console.WriteLine(racer); }
9,使用Skip()方法和Take()方法分页
Skip()方法:跳过序列中指定数量的元素,然后返回剩余的元素。
Take()方法:从序列的开头返回指定数量的连续元素。
int pageSize = 5; int numberPages = (int) Math.Ceiling(Formula1.GetChampion().Count/(double) pageSize); for (int page = 0; page < numberPages; page++) { Console.WriteLine($"Page {page+1}"); var racers = (from r in Formula1.GetChampion() orderby r.LastName, r.FirstName select r.ToString()). Skip(page*pageSize).Take(pageSize); foreach (var name in racers) { Console.WriteLine(name); } }
输出(前三页):
Page 1
Fernando Alonso
Mario Andretti
Alberto Ascari
Jack Brabham
Jenson Button
Page 2
Jim Clark
Juan Manuel Fangio
Nino Farina
Emerson Fittipaldi
Kimi Green
Page 3
Mika Hakkinen
Lewis Hamilton
Mike Hawthorn
Damon Hill
Graham Hill
10,聚合操作符
Count方法:
var query = from r in Formula1.GetChampion() let numberYears = r.Years.Count() where numberYears >= 3 orderby numberYears descending, r.LastName select new { Name = r.ToString(), TimesChampion = numberYears }; foreach (var r in query) { Console.WriteLine($"{r.Name} {r.TimesChampion}"); }
输出:
Michael Schumacher 7
Juan Manuel Fangio 5
Alain Prost 4
Jack Brabham 3
Niki Lauda 3
Nelson Piquet 3
Ayrton Senna 3
Jackie Stewart 3
用Sum()方法计算一个国家赢得比赛的总次数
var countries = (from c in from r in Formula1.GetChampion() group r by r.Country into c select new { Country = c.Key, Wins = (from r1 in c select r1.Wins).Sum() } orderby c.Wins descending, c.Country select c ).Take(5); foreach (var country in countries) { Console.WriteLine($"{country.Country} {country.Wins}"); }
输出:
UK 167
Germany 112
Brazil 78
France 51
Finland 42
11,转换操作符
ToList()方法
List<Racer> racers = (from r in Formula1.GetChampion() where r.Starts > 150 orderby r.Starts descending select r).ToList(); foreach (var racer in racers) { Console.WriteLine($"{racer} {racer:S}"); }
输出:
Michael Schumacher 287
Jenson Button 208
Nelson Piquet 204
Alain Prost 197
Nigel Mansell 187
Fernando Alonso 177
Graham Hill 176
Niki Lauda 173
Jacques Villeneuve 165
Ayrton Senna 161
Mika Hakkinen 160
12,生成操作符
var values = Enumerable.Range(1, 20); foreach (var item in values) { Console.Write($"{item} "); }
输出:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
13,表达式树看不懂