<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
1、使用 join 子句 根據特定的條件合併兩個資料來源,但之前要獲得兩個要連線的列表。
業務說明:返回1958到1965年間的車手冠軍和車隊冠軍資訊,根據年份關聯
var racers = from r in Formula1.GetChampions() from y in r.Years select new { Year = y, Name = r.FirstName + " " + r.LastName }; var teams = from t in Formula1.GetContructorChampions() from y in t.Years select new { Year = y, Name = t.Name }; var racersAndTeams0 = (from r in racers join t in teams on r.Year equals t.Year orderby t.Year select new { Year = r.Year, Racer = r.Name, Team = t.Name }).Take(10);
方法語法:
var racersAndTeams = racers .Join(teams, r => r.Year, t => t.Year, (r, t) => new { Year = r.Year, Racer = r.Name, Team = t.Name }) .OrderBy(p => p.Year).Take(10);
結果:
Year Champion Constructor Title
1958: Mike Hawthorn Vanwall
1959: Jack Brabham Cooper
1960: Jack Brabham Cooper
1961: Phil Hill Ferrari
1962: Graham Hill BRM
1963: Jim Clark Lotus
1964: John Surtees Ferrari
1965: Jim Clark Lotus
1966: Jack Brabham Brabham
1967: Denny Hulme Brabham
2、或者合併成一個LINQ 查詢
var racersAndTeams = (from r in from r1 in Formula1.GetChampions() from yr in r1.Years select new { Year = yr, Name = r1.FirstName + " " + r1.LastName } join t in from t1 in Formula1.GetContructorChampions() from yt in t1.Years select new { Year = yt, Name = t1.Name } on r.Year equals t.Year orderby t.Year select new { Year = r.Year, Racer = r.Name, Team = t.Name }).Take(10);
方法語法
var racersAndTeams0 = Formula1.GetChampions() .SelectMany(m => m.Years, (m, y) => new { Racer = m, Year = y }) .Join(Formula1.GetContructorChampions() .SelectMany(m => m.Years, (m, y) => new { Team = m, Year = y }) , m => m.Year, m1 => m1.Year , (m, m1) => new { Year = m.Year, Racer = m.Racer.FirstName + " " + m.Racer.LastName, Team = m1.Team.Name }) .OrderBy(m => m.Year).Take(10);
左外連線返回左邊序列中的全部元素,即使它們在右邊的序列中並沒有匹配的元素。
左外連線用join子句和 DefaultIfEmpty 方法定義。 使用 DefaultIfEmpty 定義其右側的預設值。
linq只支援左連線,如要右連線,將query和query1調換位置
業務說明:如賽車手比車隊設立冠軍的年份要早,可能某個年份只有賽車手冠軍沒有車隊冠軍,這時候需要左連線查詢。
var racers = from r in Formula1.GetChampions() from y in r.Years select new { Year = y, Name = r.FirstName + " " + r.LastName }; 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 into rt from t in rt.DefaultIfEmpty() orderby r.Year select new { Year = r.Year, Champion = r.Name, Constructor = t == null ? "no constructor championship" : t.Name }).Take(10); foreach (var item in racersAndTeams) { Console.WriteLine("{0}: {1,-20} {2}", item.Year, item.Champion, item.Constructor); }
結果
1950: Nino Farina no constructor championship
1951: Juan Manuel Fangio no constructor championship
1952: Alberto Ascari no constructor championship
1953: Alberto Ascari no constructor championship
1954: Juan Manuel Fangio no constructor championship
1955: Juan Manuel Fangio no constructor championship
1956: Juan Manuel Fangio no constructor championship
1957: Juan Manuel Fangio no constructor championship
1958: Mike Hawthorn Vanwall
1959: Jack Brabham Cooper
左外連線使用了組連線和 into 子句。它有一部分與組連線相同,只不過組連線不適用 DefaultIfEmpty 方法。
使用組連線時,基於鍵相等對兩個兩個獨立的序列的元素進行關聯並對結果進行分組。
常應用於返回“主鍵物件-外來鍵物件集合”形式的查詢。
業務說明:返回1958到1965年間的車手冠軍和車隊冠軍資訊,根據年份關聯並分組
注意:直接出現在join子句之後的into關鍵字會被翻譯為GroupJoin,而在select或group子句之後的into表示繼續一個查詢。
// 查詢表示式 var racersAndTeams =( from r in racers join t in teams on r.Year equals t.Year into groupTeams select new { Year = r.Year, Racer = r.Name, GroupTeams = groupTeams }).Take(10);
方法語法:
var racersAndTeams1 = racers .GroupJoin(teams, r => r.Year, t => t.Year, (r, t) => new { Year = r.Year, Racer = r.Name, GroupTeams = t } ).Take(10);; foreach (var item in racersAndTeams) { Console.WriteLine("{0}: {1,-20} {2}", item.Year, item.Racer, item.GroupTeams.Count()); }
結果:
1950: Nino Farina 0
1952: Alberto Ascari 0
1953: Alberto Ascari 0
1951: Juan Manuel Fangio 0
1954: Juan Manuel Fangio 0
1955: Juan Manuel Fangio 0
1956: Juan Manuel Fangio 0
1957: Juan Manuel Fangio 0
1958: Mike Hawthorn 1
1961: Phil Hill 1
2、join…on…equals…支援多個鍵關聯,可以使用匿名型別來對多個鍵值進行Join,如下所示:
// 查詢表示式 var query17 = from r in racers join r2 in teams on new { Name = r.Name.Substring(0, 1), Year = r.Year } equals new { Name = r2.Name.Substring(0, 1), Year = r2.Year } into yearResults select new { Results = yearResults }; foreach (var item in query17) { foreach (var info in item.Results) { Console.WriteLine(info.Name); } } //McLaren
集合操作通過呼叫實體類的 GetHashCode() 和 Equals() 方法比較物件。 對於自定義比較,可以傳遞實現 IEqualityComparer介面的物件。
業務說明:獲取使用車型”Ferrari”和車型”Mclaren”都獲得過車手冠軍車手列表
void Main() { Func<string, IEnumerable<Racer>> racersByCar = car => from r in Formula1.GetChampions() from c in r.Cars where c == car orderby r.LastName select r; foreach (var racer in racersByCar("Ferrari").Intersect(racersByCar("McLaren"), new RacerComparer())) { Console.WriteLine(racer); } } public class RacerComparer : IEqualityComparer<Racer> { public bool Equals(Racer x, Racer y) { if (Object.ReferenceEquals(x, y)) return true; return x != null && y != null && x.FirstName == y.FirstName && x.LastName == y.LastName; } public int GetHashCode(Racer obj) { int hashStudentId = obj.FirstName.GetHashCode(); int hashScore = obj.LastName.GetHashCode(); return hashStudentId ^ hashScore; } }
結果:
Niki Lauda
範例:合併html開始標籤和結束標籤
var letters = new string[] { "A", "B", "C", "D", "E" }; var numbers = new int[] { 1, 2, 3 }; var q = letters.Zip(numbers, (l, n) => l + n.ToString()); foreach (var s in q) Console.WriteLine(s);
結果:
A1
B2
C3
範例:
int[] arr1 = { 1, 4, 7, 9 }; int[] arr2 = { 1, 7, 9, 4 }; Console.WriteLine("排序前 是否相等:{0}" , arr1.SequenceEqual(arr2) ? "是" : "否"); // 否 Console.WriteLine(); Console.WriteLine("排序後 是否相等:{0}" , arr1.SequenceEqual(arr2.OrderBy(k => k)) ? "是" : "否"); // 是
擴充套件方法 Take() 和 Skip() 等的分割區操作可以用於分頁。
新增在查詢的“最後”,返回集合的一個子集。
從序列的開頭返回指定數量的連續元素。
只要滿足指定的條件,就會返回序列的元素。
從第一個元素開始, 讀取Starts小於40的人員列表,只要遇到大於40的元素就立即停止返回。
var racers = (from r in Formula1.GetChampions() orderby r.Starts select r ) <strong>.TakeWhile(p </strong><strong>=> p.Starts < 40</strong><strong>);</strong> foreach (var name in racers) { Console.WriteLine($"{name:A}"); }
結果:
Alberto Ascari, Italy; starts: 32, wins: 10
Nino Farina, Italy; starts: 33, wins: 5
跳過序列中指定數量的元素,然後返回剩餘的元素。
業務說明:將車手冠軍列表按每頁5個名字進行分頁。
int pageSize = 5; int numberPages = (int)Math.Ceiling(Formula1.GetChampions().Count() / (double)pageSize); for (int page = 0; page < numberPages; page++) { Console.WriteLine("Page {0}", page); var racers = ( from r in Formula1.GetChampions() orderby r.LastName select r.FirstName + " " + r.LastName ) .Skip(page * pageSize).Take(pageSize); foreach (var name in racers) { Console.WriteLine(name); } }
結果:
Page 0
Fernando Alonso
Mario Andretti
Alberto Ascari
Jack Brabham
Jim Clark
Page 1
Juan Manuel Fangio
Nino Farina
Emerson Fittipaldi
Mika Hakkinen
Mike Hawthorn
只要滿足指定的條件,就跳過序列中的元素,然後返回剩餘元素。
聚合操作符返回一個值。
業務說明:下面的Count 方法只返回獲得冠軍次數超過三次的賽車手,因為同一個查詢中需要使用同一個計數超過一次,所以使用let 子句定義了一個變數 numberYear.
var query = from r in Formula1.GetChampions() let numberYears = r.Years.Count() where numberYears >= 3 orderby numberYears descending, r.LastName select new { Name = r.FirstName + " " + r.LastName, TimesChampion = numberYears }; foreach (var r in query) { Console.WriteLine("{0} {1}", 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 方法用於計算一個國家贏得比賽的總次數。
首先根據國家對賽車手分組,再在新建立的匿名型別中,把Wins 屬性賦予某個國家贏得比賽的總次數。
var countries = (from c in from r in Formula1.GetChampions() 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("{0} {1}", country.Country, country.Wins); } //UK 138 //Germany 91 //Brazil 78 //France 51 //Finland 40
業務說明:Aggregate的
第一個引數是演演算法的種子,即初始值。(可選)
第二個引數是一個表示式,用來對每個元素進行計算(委託第一個引數是累加變數,第二個引數當前項)。
第三個引數是一個表示式,用來對最終結果進行資料轉換。
int[] numbers = { 1, 2, 3 }; int y = numbers.Aggregate((tol, n) => prod + n); // 1+2+3 = 6 int x = numbers.Aggregate(0, (tol, n) => tol + n); // 0+1+2+3 = 6 int z = numbers.Aggregate(0, (tol, n) => tol + n, r => r * 2);// (0+1+2+3)*2 = 12
查詢可以推遲到存取資料項時再執行。在迭代中使用查詢時,查詢會執行。
而使用轉換操作符會立即執行查詢,把查詢結果放在陣列、列表或字典中。
LINQ本身支援四種不同的集合生成方式,包含生成陣列的ToArray()
、生成列表的ToList
、生成字典集合的ToDictionary
以及生成Lookup<tkey,telement>
類的ToLookup
。
將非泛型的 IEnumerable 集合元素轉換為指定的泛型型別,若型別轉換失敗則丟擲異常。
如果需要在非型別化的集合上(如ArrayList
)使用LINQ 查詢,就可以使用Cast 方法。
在下面的例子中,基於Object
型別的ArrayList
集合用Racer物件填充。
var list = new ArrayList(Formula1.GetChampions() as System.Collections.ICollection); var query = from r in list.Cast() where r.Country == "USA" orderby r.Wins descending select r; foreach (var racer in query) { Console.WriteLine("{0:A}", racer); } //Mario Andretti, USA; starts: 128, wins: 12 //Phil Hill, USA; starts: 48, wins: 3
從 IEnumerable 建立一個陣列。
立即執行查詢,從 IEnumerable 建立一個 List。
根據指定的鍵選擇器函數,從 IEnumerable 建立一個 Dictionary<tkey,tvalue>。
將列表轉換為字典:
var spartans = new List<dynamic> { new {Opponent="UAB",Score="55-18"}, new {Opponent="Bowling Green",Score="55-18"}, new {Opponent="Pittsburgh",Score="55-18"}, new {Opponent="Notre Dame",Score="55-18"} }; //字典是一種鍵值對的集合,ToDictionary 將一個IEnumerable<T>物件(比如LINQ查詢所返回的結果) //轉換為一個IDictionary<Key,Value>物件。 IDictionary<string, dynamic> stats = spartans.ToDictionary(key => (string)key.Opponent); Console.WriteLine("Spartans vs. {0} {1}", stats["Notre Dame"].Opponent, stats["Notre Dame"].Score);
根據指定的鍵選擇器函數,從 IEnumerable 建立一個 System.Linq.Lookup。
ToLookup使用比較複雜,Lookup類似於Dictionary,不過,Dictionary每個鍵只對應一個值,而Lookup則是1:n 的對映。
Lookup沒有公共建構函式,而且是不可變的。在建立Lookup之後,不能新增或刪除其中的元素或鍵。(可以將ToLookup 視為GroupBy與ToDictionary的功能合體)
業務說明:將車手冠軍按其使用車型進行分組,並顯示使用”williams”車型的車手名字。
ILookup<string, Racer> racers = (from r in Formula1.GetChampions() from c in r.Cars //使用複合的from 查詢 select new { Car = c, Racer = r } ).ToLookup(cr => cr.Car, cr => cr.Racer); if (racers.Contains("Williams")) { foreach (var williamsRacer in racers["Williams"]) { Console.WriteLine(williamsRacer); } } //Alan Jones //Keke Rosberg //Nelson Piquet //Nigel Mansell //Alain Prost //Damon Hill //Jacques Villeneuve
返回指定序列的元素;如果序列為空,則返回包含型別引數的預設值的單一元素集合 。
var defaultArrCount = (new int[0]).DefaultIfEmpty().Count(); Console.WriteLine(defaultArrCount); //1
返回型別為 IEnumerable 。用於處理LINQ to Entities操作遠端資料來源與本地集合的共同作業
生成操作符返回一個新的集合。三個生成操作符不是擴充套件方法,而是返回序列的正常靜態方法。
生成一個具有指定型別引數的空序列 IEnumerable。
Empty() 方法返回一個不返回值的迭代器,用於需要一個集合的引數,可以給引數傳遞空集合。
string[] names1 = { "Hartono, Tommy" }; string[] names2 = { "Adams, Terry", "Andersen, Henriette Thaulow", "Hedlund, Magnus", "Ito, Shu" }; string[] names3 = { "Solanki, Ajay", "Hoeing, Helge", "Andersen, Henriette Thaulow", "Potra, Cristina", "Iallo, Lucio" }; List<string[]> namesList = new List<string[]> { names1, names2, names3 }; IEnumerable<string> allNames = namesList.Aggregate(Enumerable.Empty<string>(), (current, next) => next.Length > 3 ? current.Union(next) : current); foreach (string name in allNames) { Console.WriteLine(name); } //Adams, Terry //Andersen, Henriette Thaulow //Hedlund, Magnus //Ito, Shu //Solanki, Ajay //Hoeing, Helge //Potra, Cristina //Iallo, Lucio
生成指定範圍內的整數的序列 IEnumerable。
如需要填充一二範圍的數位,此時就應使用 Range() 方法。這個方法第一個引數作為起始值,把第二個引數作為要填充的項數。
var values = Enumerable.Range(1, 20); foreach (var value in values) { Console.WriteLine(value); } // 結果 1 2 3 4 5 6 ...... 19 20
Range() 方法不返回填充所定義值的集合,與其他方法一樣,推遲查詢,返回一個 RangeEnumerator。其中用 yield return 語句,來遞增值。該結果也可以與其他擴充套件方法一起用。
var values = Enumerable.Range(1, 5).Select(n => n * 3); foreach (var value in values) { Console.WriteLine(value); } // 3 6 9 12 15
生成包含一個重複值的序列 IEnumerable。
Repeat() 方法 返回一個迭代器,把同一個值重複特定的次數。
IEnumerable<string> strings = Enumerable.Repeat("I like programming.", 3); foreach (String str in strings) { Console.WriteLine(str); } //I like programming. //I like programming. //I like programming.
如果元素序列滿足指定的條件,量詞操作符就返回布林值。
確定序列是否包含任何元素;或確定序列中的任何元素是否都滿足條件。
//獲取是否存在姓為「Schumacher」的車手冠軍 var hasRacer_Schumacher = Formula1.GetChampions().Any(r => r.LastName == "Schumacher"); Console.WriteLine(hasRacer_Schumacher); //True
確定序列中的所有元素是否滿足條件。
確定序列是否包含指定的元素。
這些元素操作符僅返回一個元素,不是IEnumerable。(預設值:值型別預設為0,參照型別預設為null)
業務說明:獲取冠軍數排名第三的車手冠軍
var Racer3 = Formula1.GetChampions() .OrderByDescending(r => r.Wins) .ElementAtOrDefault(2); Console.WriteLine(Racer3); //Ayrton Senna
AsParallel() 方法,擴充套件 IEnumerable 介面,返回 ParallelQuery類,所以正常的集合類可以以平行方式查詢。
var query24 = from r in Formual.GetChampions().AsParallel() select r;
AsParallel()方法不僅擴充套件了 IEnumerable 介面,還擴充套件了 Partitioner 類。通過它,可以影響建立的分割區。
手動建立一個分割區器
var query25 = from r in Partitioner.Create (Formual.GetChampions(), true).AsParallel() select r;
.NET 提供一個標準方法,來取消長時間執行的任務,也適用於並行Linq。
要取消長時間執行的查詢可以給查詢新增WithCancellation() 方法,並傳遞一個 CancellactionToken令牌作為引數。
CancelllationToken令牌從CancellactionTokenSource類中建立。該查詢在單獨的執行緒中執行,在該執行緒中,捕獲一個OperationCanceledException型別的異常。如果取消了查詢就觸發這個異常。
在主執行緒中,呼叫CancellationTokenSource類的Cancel()方法可以取消任務。
CancellationTokenSource cts = new CancellationTokenSource(); Task.Factory.StartNew(() => { try { var res = from r in Formual.GetChampions().AsParallel().WithCancellation(cts.Token) select r; Console.WriteLine("query finished, sum:{0}", res); } catch (OperationCanceledException ex) { Console.WriteLine("canceled!"); Console.WriteLine(ex.Message); } }); string input = Console.ReadLine(); if (input.ToLower().Equals("y")) { cts.Cancel(); Console.WriteLine("canceled 2!"); }
到此這篇關於C#使用LINQ查詢操作符的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45