鼎鼎知识库
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

7.Linq.md 8.7KB

před 5 roky
před 5 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. > Linq概述
  2. - Linq(语言集成查询)在C#中集成了查询语法,可以用相同的语法访问不同的数据源。Linq提供了不同数据源的抽象层,所以可以使用相同的语法。
  3. > 标准的查询操作符
  4. - Where OffType<TResult>
  5. - 筛选操作符定义了返回元素的条件。在Where查询操作符中可以使用谓词。例如,lambda表达式定义的谓词,来返回布尔值。OfType<TResult>根据类型筛选元素,只返回TResult类型的元素
  6. - Select SelectMany
  7. - 投射操作符用于把对象转换为另一个类型的新对象。Select和SelectMany定义了根据选择器函数选择结果值得投射
  8. - OrderBy\ThenBy\OrderByDescending\ThenByDescending\ThenByDescending\Reverse
  9. - 排序操作符改变所返回的元素的顺序。OrderBy按升序排序,OrderByDescending按降序排序。如果第一次排序的结果很类似,就可以使用ThenBy和ThenBy Deacending 操作符进行第二次排序。Reverse反转集合中元素的顺序
  10. - Join\GroupJoin
  11. -连接操作符用于合并并不直接相关的集合。使用Join操作符,可以根据键选择器函数连接两个集合,这个类似于SQL中的JOIN。GroupJoin操作符连接两个集合,组合其结果
  12. - GroupBy\ToLookup
  13. - 组合操作符把数据放在组中。GroupBy操作符组合有公共键的元素。ToLookup通过创建一个一对多字典,来组合元素
  14. - Any\All\Contains
  15. - 如果元素序列满足指定的条件,限定符操作符就返回布尔值。Any确定集合中是否有满足为此函数的元素;All确定集合中的所有元素是否都满足谓词函数;Contains检查某个元素是否在集合中
  16. - Take\Skip\TakeWhile\SkipWhile
  17. - 分区操作符返回集合的一个子集。Take、Skip、TakeWhile和SkipWhile都是分区操作符。使用它们可以得到部分结果。使用Take必须指定要从集合中提取的元素个数;Skip跳过指定的元素个数,提取其他元素;TakeWhile提取条件为真的元素,SkipWhile跳过条件为真的元素。
  18. - Distinct\Union\Intersect\Except\Zip
  19. - Set操作符返回一个集合。Distinct从集合中删除重复的元素,除了Distinct之外,其他Set操作符都需要两个集合。Union返回出现在其中一个集合中的唯一元素。Intersect返回两个集合中都有的元素。Except返回只出现在一个集合中的元素。Zip把两个集合合并为一个。
  20. - First\FirstOrDefault\Last\LastOrDefault\ElementAt\ElementAtOrDefault\Single\SingleOrDefault
  21. - 这些元素操作符仅返回一个元素。First返回第一个满足条件的元素。FirstOrDefault类似于First,但如果没有找到满足条件的元素,就返回类型的默认值。Last返回最后一个满足条件的元素。ElemAt指定了要返回的元素的位置。Single只返回一个满足条件的元素。如果有多个元素都满足条件,就抛出一个异常。所有的XXOrDefault方法都类似与以相同前缀开头的方法,但如果没有找到该元素,他们就返回类型的默认值
  22. - Count\Sum\Min\Max\Average\Aggregate
  23. - 聚合操作符计算集合的一个值。利用这些聚合操作福,可以计算所有值得总和、所有元素的个数、值最大和最小的元素,以及平均值等
  24. - ToArray\AsEnumerable\ToList\ToDictionary\Cast<TResult>
  25. - 这些转换操作符将集合转换为数组:IEnumerable、IList、IDictionary等。Cast方法把集合的每个元素类型转换为泛型参数类型
  26. - Empty\Range\Repeat
  27. - 这些生成操作符返回一个心机和。使用Empty时集合时空的:Range返回一系列数字:Repeat返回一个始终重复一个值得集合
  28. **筛选**
  29. - 使用where子句,可以合并多个表达式。例如,找出赢得至少15场比赛的巴西和奥地利赛车手。
  30. ```
  31. var racers = from r in Formulal.GetChampions()where r.Wins> 15 &&(r.Country=="Brazil" || r.Country="Austria") select r;
  32. foreach(var r in rqacers)
  33. {
  34. WriteLine($"{r:A}");
  35. }
  36. var racers=Formulal.GetChampions().Where(r=>r.Wins>15 &&(r.Country=="Brazil" || r.Country== "Austria")).Select(r=>r);
  37. ```
  38. > 用索引筛选
  39. - 不能使用Linq查询的一个例子是Where()方法的重载。在Where()方法的重载中,可以传递第二个参数--索引。索引是筛选器返回的每个结果的计数器。可以在表达式中使用这个索引,执行基于索引的计算。
  40. ```
  41. var racers =Formulal.GetChamplons().Where((r,index)=>r.LastName.StartsWith("A") && index%2!=0);
  42. foreach (var r in racers)
  43. {
  44. WriteLine(${r:A});
  45. }
  46. ```
  47. > 类型筛选
  48. -为了基于类型的筛选,可以使用OfType()扩展方法。这里数组数据包含string和int对象。使用OfType()扩展方法,把string类传送给泛型参数,就从集合中仅返回字符串
  49. ```
  50. object[] data={"one",2,3,"four","five",6};
  51. var query=data.OfType<string>();
  52. foreach(var s in query)
  53. {
  54. WriteLine(s);
  55. }
  56. ```
  57. > LINQ查询中的变量
  58. - 在为分组编写的LINQ查询中,Count方法调用了多次。使用了let子句可以改变这种方式。let允许在LINQ查询中定义变量:
  59. ```
  60. var countries=Formulal.GetChampions().GroupBy(r=>r.Country).Select(g=>new{Group=g,Count=g.Count()}).OrderByDescending(g=>g.Count).ThenBy(g=>g.Group.Key).Where(g=>g.Count>=2).Select(g=>new
  61. {
  62. Country=g.Group.Key,
  63. Count=g.Count
  64. });
  65. ```
  66. > 内连接
  67. - 使用join子句可以根据特定的条件合并两个数据源,但之前要获得两个要连接的列表。
  68. - 例子:在一级方程式比赛中,有赛车手冠军和车队冠军。赛车手从GetChampions()方法中返回,车队从GetConstructorChampions()方法中返回。现在要获得一个年份表,列出每年的赛车手冠军和车队冠军
  69. - 先定义两个查询,用于查询赛车手和车队
  70. ```
  71. var racers=from r in Formulal.GetChampions() from y in r.Years select new
  72. {
  73. Year=y,
  74. Name=r.FirstName+""+r.LastName
  75. };
  76. var teams=from t in Formulal.GetContructorChampions() from y in t.Years select new
  77. {
  78. Year =y,
  79. Name=t.Name
  80. };
  81. ```
  82. - 有了这两个查询,再通过join子句,根据赛车手获得冠军的年份和车队获得冠军的年年份进行连接。select子句定义了一个新的匿名类型,它包含Year、Racer和Team属性。
  83. ```
  84. var racersAndTeams=(from r in racers join t in teams on r.Year equals t.Year select new
  85. {
  86. r.Year,
  87. Champion=r.Name,
  88. Constructor=t.Name
  89. }).Take(10);
  90. WriteLine("Year World Champion\t Constructor Title");
  91. foreach (var item in racersAndTeams)
  92. {
  93. WriteLine($"{item.Year}:{item.Champion,-20}{item.Constructor}");
  94. }
  95. 也可以把它们合并为一个LINQ查询
  96. var racersAndTeams=
  97. {
  98. from r in
  99. from r1 in Formulal.GetChampions()
  100. from yr in r1.Years
  101. select new
  102. {
  103. Year=yr,
  104. Name=r1.FirstName + "" +r1.LastName
  105. }
  106. join t in
  107. from t1 in Formulal.GetContructorChampios()
  108. from yt in t1.Years select new
  109. {
  110. Year=yt,
  111. Name=t1.Name
  112. }
  113. on r.Year equals t.Year
  114. orderby new
  115. {
  116. Year=r.Year,
  117. Racer=r.Name,
  118. Team=t.Name
  119. }).Take(10);
  120. }
  121. ```
  122. > 左外连接
  123. - 左外连接用join子句和DefaultIfEmpty方法定义。
  124. ```
  125. var racersAndTeams=
  126. (from r in racers
  127. join t in teams on r.Year equals t.Year into rt from t in rt.DefaultIfEmpty() orderby r.Year select new
  128. {
  129. Year=r.Year,
  130. Champion=r.Name,
  131. Constructor=t==null?"no constructor championship":t.Name
  132. }).Take(10);
  133. ```
  134. > 组连接
  135. - 左外连接使用了组连接和into子句。它有一部分语法与组连接相同,只不过组连接不使用DefaultIfEmpty方法。
  136. - 使用组连接时,可以连接两个独立的序列,对于其中一个序列中的某个元素,另一个序列中在对应的一个项列表。
  137. > 集合操作
  138. - 扩展方法Distinct(),Union(),Intersect(),Except()都是集合操作。
  139. - 集合操作通过调用实体类的GetHashCode()和Equals()方法来比较对象。对于自定义比较,还可以传递一个实现了IEqualityComparer<T>接口的对象。
  140. > 合并
  141. - Zip()方法允许用一个谓词函数把两个相关的序列合并为一个。
  142. ```
  143. var racerNames=from r in Formulal.GetChampions() where r.Country=="Italy" orderby r.Wins descending select new
  144. {
  145. Name=r.FiretName+""+r.LastName
  146. };
  147. var racerNamesAndStarts=from r in Formulal.GetChampions() where r.Country=="Italy" orderby r.Wins descending select new
  148. {
  149. LastName=r.LastName,
  150. Starts=r.Starts
  151. };
  152. var races=racerName.Zip(racerNamesAndStarts,
  153. (first,second)=>first.Name+",starts:"+second.Starts)
  154. foreach(var r in racers)
  155. {
  156. WriteLine(r);
  157. }
  158. ```