C# System.Linq 萬能的查詢語句示例詳解
首先是官方文檔:
System.Linq 命名空間 | Microsoft Docs
Enumerable 類 (System.Linq) | Microsoft Docs
合理的使用System.Linq 類庫,可以讓代碼更加高效簡潔,對操作繼承IEnumerable的數(shù)據(jù)類型(數(shù)組、List、Dictionary等)可以快速高效的做一些操作,比如在字典中根據(jù)Value值獲取對應(yīng)的Key,常規(guī)方法就是遍歷比較,使用Linq庫的"FirstOrDefault"或"Whrer"則會更加快捷。
Linq查詢有兩種形式的語法:查詢語法和方法語法
1. 查詢語法:使用查詢表達(dá)式的形式,類似SQL語句
var value00 = from item in array1 select item;
2. 方法語法:使用方法調(diào)用的形式
value00 = array1.Select(item => item);
下面是示例:
一、準(zhǔn)備工作
先準(zhǔn)備幾個測試類
public class PlayerGroup { public Player[] players; } public class EnemyGroup { public Enemy[] enemies; } public class Player { public Player(string _name, int _level) { name = _name; level = _level; attack = level / 2 * 10; } public string name; public int level; public int attack; } public class Enemy { public Enemy(string _name, int _level) { name = _name; level = _level; attack = level / 2 * 10; } public string name; public int level; public int attack; }
在準(zhǔn)備幾個測試數(shù)組(其他實現(xiàn)了IEnumerable<>接口的系列也可)
int[] array1 = new int[] { 0, 1, 2, 3, 4, }; int[] array2 = new int[] { 5, 6, 7, 8, 9, }; Player[] array3 = new Player[] { new Player("p01", 1), new Player("p02", 2), new Player("p03", 3), new Player("p04", 4), new Player("p05", 5), new Player("p06", 6), new Player("p07", 7), new Player("p08", 8), new Player("p09", 9), new Player("p10", 10), }; Enemy[] array4 = new Enemy[] { new Enemy("e01", 6), new Enemy("e02", 7), new Enemy("e03", 8), new Enemy("e04", 9), new Enemy("e05", 10), new Enemy("e06", 11), new Enemy("e07", 12), new Enemy("e08", 13), new Enemy("e09", 14), new Enemy("e10", 15), }; PlayerGroup[] array5 = new PlayerGroup[2] { new PlayerGroup() { players = new Player[]{ new Player("pm11", 1), new Player("pm12", 1) } }, new PlayerGroup() { players = new Player[]{ new Player("pm21", 2), new Player("pm22", 2) } } }; EnemyGroup[] array6 = new EnemyGroup[2] { new EnemyGroup() { enemies = new Enemy[]{ new Enemy("em11", 2), new Enemy("em12", 2) } }, new EnemyGroup() { enemies = new Enemy[]{ new Enemy("em21", 3), new Enemy("em22", 3) } } }; int[] array7 = new int[] { 1, 2, 2, 3, 4, 5, 5, 6 };
為了方便查看結(jié)果,對序列元素的log做一下處理
private void TestLog(IEnumerable enumerable) { if (enumerable == null) Debug.Log("enumerable is null"); else { string logStr = ""; foreach (var item in enumerable) { logStr += " - " + item; } Debug.Log(logStr); } }
二、查詢語法的查詢子句,以及部分對應(yīng)的方法語法的運算
1. from:指定要作為數(shù)據(jù)來源使用的數(shù)據(jù)集合
//from:指定要作為數(shù)據(jù)來源使用的數(shù)據(jù)集合 //指定以array1作為數(shù)據(jù)來源 var value01 = from item in array1 select item; TestLog(value01); // - 0 - 1 - 2 - 3 - 4 //from可以有多個,每個from子句都指定了一個額外的源數(shù)據(jù)合集 //指定array3,array4兩個源數(shù)據(jù) var value02 = from item1 in array3 from item2 in array4 where item1.level == item2.level select item1.name; TestLog(value02); // - p06 - p07 - p08 - p09 - p10
2. select:指定對象的哪部分被選擇(可以是整個數(shù)據(jù)項,也可以是其中的一個或幾個字段),并將結(jié)果序列合并為一個序列
//指定選擇name字段,返回值類型var實際為IEnumerable<string> var value03 = from item in array3 select item.name; TestLog(value03); value03 = array3.Select(item => item.name); TestLog(value03); // - p01 - p02 - p03 - p04 - p05 - p06 - p07 - p08 - p09 - p10 //select:指定選擇name和attack字段,返回值類型var實際為IEnumerable<t>,t是匿名類型new{ int level, int attack } var value04 = from item in array3 where item.level < 5 select new { item.level, item.attack }; TestLog(value04); value04 = array3.Select(item => new { item.level, item.attack }); TestLog(value04); // - { level = 1, attack = 0 } - { level = 2, attack = 10 } - { level = 3, attack = 10 } - { level = 4, attack = 20 }
3. where:對序列的元素進(jìn)行篩選
//where:對array1的元素進(jìn)行篩選,只取level < 3的元素 var value05 = from item in array1 where item < 3 select item; TestLog(value05); value05 = array1.Where(item => item < 3); TestLog(value05); // - 0 - 1 - 2
4. let:接受一個表達(dá)式的運算,并賦記錄結(jié)果
//let:記錄兩個元素之和 var value06 = from item1 in array1 from item2 in array2 let sum = item1 + item2 where sum == 10 select item1 + "+" + item2 + "=10"; TestLog(value06); // - 1+9=10 - 2+8=10 - 3+7=10 - 4+6=10
5. orderby:根據(jù)一個或多個鍵對序列中的元素排序
//orderby:按照level進(jìn)行排序 var value07 = from item in array3 where item.level <= 5 orderby item.level select item.name; TestLog(value07); // - p01 - p02 - p03 - p04 - p05
6. group...by...:指定選擇的項如何被分組
//group...by...:按照attack進(jìn)行分組 var value08 = from item in array3 group item by item.attack; TestLog(value08.Select(item => item.Key + ":" + item.Count())); // - 0:1 - 10:2 - 20:2 - 30:2 - 40:2 - 50:1
7. join...on...:聯(lián)結(jié)兩個序列,作為一個新的集合
//join...on...:以array1和array2作為一個新的集合,并取其中array1元素中和array2元素中l(wèi)evel相等的元素 var value09 = from item1 in array3 join item2 in array4 on item1.level equals item2.level select item1.level; TestLog(value09); value09 = array3.Join(array4, item1 => item1.level, item2 => item2.level, (item1, item2) => item1.level); TestLog(value09); // - 6 - 7 - 8 - 9 - 10 //join...on... var value10 = from item1 in array3 join item2 in array4 on item1.level equals item2.level select new { item1.level, playerName = item1.name, enemyName = item2.name }; TestLog(value10); value10 = array3.Join(array4, item1 => item1.level, item2 => item2.level, (item1, item2) => new { item1.level, playerName = item1.name, enemyName = item2.name }); TestLog(value10); // - { level = 6, playerName = p06, enemyName = e01 } - { level = 7, playerName = p07, enemyName = e02 } - { level = 8, playerName = p08, enemyName = e03 } - { level = 9, playerName = p09, enemyName = e04 } - { level = 10, playerName = p10, enemyName = e05 }
8. into:可以記錄查詢的一部分結(jié)果,以便后續(xù)繼續(xù)使用
//into:可以記錄查詢的一部分結(jié)果,以便后續(xù)繼續(xù)使用 var value11 = from item1 in array3 join item2 in array4 on item1.level equals item2.level into temp from item3 in temp select item3.level; TestLog(value11); // - 6 - 7 - 8 - 9 - 10
三、方法語法的運算
1. Select:指定對象的哪部分被選擇(可以是整個數(shù)據(jù)項,也可以是其中的一個或幾個字段),并將結(jié)果序列合并為一個序列
//指定選擇name字段,返回值類型var實際為IEnumerable<string> var value21 = array3.Select(item => item.name); TestLog(value21); // - p01 - p02 - p03 - p04 - p05 - p06 - p07 - p08 - p09 - p10
2. Where:對序列的元素進(jìn)行篩選
//對array1的元素進(jìn)行篩選,只取level <= 5的元素 var value22 = array1.Where(item => item < 5); TestLog(value22); // - 0 - 1 - 2 - 3 - 4
3. Join:聯(lián)結(jié)兩個序列,作為一個新的集合
//以array1和array2作為一個新的集合,并取其中array1元素中和array2元素中l(wèi)evel相等的元素 var value23 = array3.Join(array4, item1 => item1.level, item2 => item2.level, (item1, item2) => item1.level); TestLog(value23); // - 6 - 7 - 8 - 9 - 10 var value24 = array3.Join(array4, item1 => item1.level, item2 => item2.level, (item1, item2) => new { item1.level, playerName = item1.name, enemyName = item2.name }); TestLog(value24); // - { level = 6, playerName = p06, enemyName = e01 } - { level = 7, playerName = p07, enemyName = e02 } - { level = 8, playerName = p08, enemyName = e03 } - { level = 9, playerName = p09, enemyName = e04 } - { level = 10, playerName = p10, enemyName = e05 }
4. SelectMany:將序列的每個元素投影到 IEnumerable<T> 并將結(jié)果序列合并為一個序列
//篩選array3中的players字段,將每個players值拆散成IEnumerable<Player>,并將所有的IEnumerable<Player>合并為一個序列 var value25 = array5.SelectMany(group => group.players); TestLog(value25); // - Player - Player - Player - Player var value26 = array5.SelectMany(group => group.players, (group, player) => player.name); TestLog(value26); // - pm11 - pm12 - pm21 - pm22
5. GroupJoin:基于鍵值等同性對兩個序列的元素進(jìn)行關(guān)聯(lián),并對結(jié)果進(jìn)行分組。 使用默認(rèn)的相等比較器對鍵進(jìn)行比較
然而并沒有搞懂···
var value27 = array5.GroupJoin(array6, group01 => group01.players.Select(item => item.level), group02 => group02.enemies.Select(item => item.level), (group, groups) => group.players.Select(p => p.name)); foreach (var item in value27) { TestLog(item); // - pm11 - pm12 // - pm21 - pm22 }
6. Take:返回序列中的前n個對象
var value28 = array1.Take(3); TestLog(value28); // - 0 - 1 - 2
7. Skip:跳過序列中的前n個對象
//Skip:跳過序列中的前n個對象 var value29 = array1.Skip(3); TestLog(value29); // - 3 - 4
8. TakeWhile:迭代序列,如果當(dāng)前項計算結(jié)果返回true,就選擇該項。在第一次返回false的時候,該項和其余項都被丟棄,不在判斷后面的項
//0返回true,1返回false,所以1及其后面的元素都丟棄 var value30 = array1.TakeWhile(i => i % 2 == 0); TestLog(value30); // - 0
9.SkipWhile:迭代序列,如果當(dāng)前項的計算結(jié)果返回true,就跳過該項。在第一次返回false的時候,該項和其余項都被選擇
//SkipWhile:迭代序列,如果當(dāng)前項的計算結(jié)果返回true,就跳過該項。在第一次返回false的時候,該項和其余項都被選擇 var value31 = array1.SkipWhile(i => i % 2 == 0); TestLog(value31); // - 1 - 2 - 3 - 4
10. Concat:連接兩個序列
var value32 = array2.Concat(array1); TestLog(value32); // - 5 - 6 - 7 - 8 - 9 - 0 - 1 - 2 - 3 - 4
11. OrderBy:根據(jù)一個或多個鍵對序列中的元素排序
var value33 = value32.OrderBy(i => i); TestLog(value33); // - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9
12. Reverse:反轉(zhuǎn)序列中的元素
var value34 = array1.Reverse(); TestLog(value34); // - 4 - 3 - 2 - 1 - 0
13. GroupBy:對序列中的元素分組
var value35 = array1.GroupBy(i => i < 3); foreach (IGrouping<bool, int> item in value35) { Debug.Log(item.Key); TestLog(item); } //True // - 0 - 1 - 2 //False // - 3 - 4
14. Distinct:去除序列中的重復(fù)項
var value36 = array7.Distinct(); TestLog(value36); // - 1 - 2 - 3 - 4 - 5 - 6
15. Union:返回兩個序列的并集
var value37 = array2.Union(array7); TestLog(value37); // - 5 - 6 - 7 - 8 - 9 - 1 - 2 - 3 - 4
16. Intersect:返回兩個序列的交集
var value38 = array1.Intersect(array7); TestLog(value38); // - 1 - 2 - 3 - 4
17. Except:返回第一個序列中不重復(fù)的元素減去同樣位于第二個序列中的元素
var value39 = array7.Intersect(array1); TestLog(value39); // - 1 - 2 - 3 - 4
18. AsEnumerable:將序列作為IEnumerable<TSource>返回
var value40 = array1.AsEnumerable(); Debug.Log(value40.GetType());
19.ToArray:將序列作為數(shù)組返回
var value41 = array1.ToArray(); Debug.Log(value41.GetType()); //System.Int32[]
20. ToList:將序列作為List<T>返回
var value42 = array1.ToList(); Debug.Log(value42.GetType()); //System.Collections.Generic.List`1[System.Int32]
21. ToDictionaty:將序列作為Dictionary<TKey,TElement>
var value43 = array1.ToDictionary(i => i); Debug.Log(value43.GetType()); //System.Collections.Generic.Dictionary`2[System.Int32,System.Int32]
22. ToLookup:將序列作為LookUp<TKey,TElement>
var value44 = array1.ToLookup(i => i); Debug.Log(value44.GetType()); //System.Linq.Lookup`2[System.Int32,System.Int32]
23. OfType:所返回的序列中元素是指定類型的元素
var value45 = array1.OfType<int>(); TestLog(value45); // - 0 - 1 - 2 - 3 - 4
24. Cast:將序列中所有的元素強(qiáng)制轉(zhuǎn)換為給定的類型
var value46 = array1.Cast<string>(); Debug.Log(value46.GetType()); //System.Linq.Enumerable+<CastIterator>d__34`1[System.String]
25. SequenceEqual:返回一個布爾值,指定兩個序列是否相等
var value47 = array1.SequenceEqual(array2); Debug.Log(value47); //False
26.1 First:返回序列中第一個匹配的元素。如果沒有元素匹配,拋出異常。如果沒有給出條件,返回序列的第一個元素
26.2 FirstOrDefault:返回序列中第一個匹配的元素。如果沒有元素匹配,返回該類型的默認(rèn)值。如果沒有給出條件,返回序列的第一個元素
var value48 = array1.First(); Debug.Log(value48); //0 value48 = array1.First(i => i > 2); Debug.Log(value48); //3 value48 = array1.FirstOrDefault(i => i > 10); Debug.Log(value48); //0
27.1 Last:返回序列中最后一個匹配的元素。如果沒有元素匹配,拋出異常。如果沒有給出條件,返回序列的最后一個元素
27.2LastOrDefault:返回序列中最后一個匹配的元素。如果沒有元素匹配,就返回默認(rèn)值。如果沒有給出條件,返回序列的最后一個元素
var value48 = array1.First(); Debug.Log(value48); //0 value48 = array1.First(i => i > 2); Debug.Log(value48); //3 value48 = array1.FirstOrDefault(i => i > 10); Debug.Log(value48); //0
28.1 Single:返回序列中匹配的單個元素。如果沒有元素匹配,或多于一個元素匹配,拋出異常
28.2 SingleOrDefault:返回序列中匹配的單個元素。如果沒有元素匹配,返回默認(rèn)值。如果多于一個元素匹配,拋出異常
var value49 = array7.Single(i => i == 1); Debug.Log(value49); //1 //value49 = array7.Single(i => i == 2); //Debug.Log(value49); //報錯(InvalidOperationException: Sequence contains more than one matching element) value49 = array7.SingleOrDefault(i => i == 10); Debug.Log(value49); //0 //value49 = array7.SingleOrDefault(i => i == 2); //Debug.Log(value49); //報錯(InvalidOperationException: Sequence contains more than one matching element)
29.1 ElementAt:返回序列中指定索引處的元素;如果索引超出范圍,拋出異常
29.2 ElementAtOrDefault:返回序列中指定索引處的元素;如果索引超出范圍,返回默認(rèn)值
var value50 = array1.ElementAt(1); Debug.Log(value50); //1 var value51 = array1.ElementAtOrDefault(10); Debug.Log(value51); //0
30. DefaultIfEmpty:返回指定序列中的元素;如果序列為空,則返回集合中類型參數(shù)的默認(rèn)值
List<int> array8 = new List<int>(); var value52 = array8.DefaultIfEmpty(); TestLog(value52); // - 0
31. Range:生成指定范圍內(nèi)的整數(shù)的序列。給定一個start整型和count整型,返回序列包含count個整型,其中第一個元素的值為start,之后每個后續(xù)元素都比前一個大1
var value53 = Enumerable.Range(10, 3); TestLog(value53); // - 10 - 11 - 12
32. Repeat:生成包含一個重復(fù)值的序列
var value54 = Enumerable.Repeat(10, 3); TestLog(value54); // - 10 - 10 - 10
33. Empty:返回給定類型T的空序列
var value55 = Enumerable.Empty<int>(); Debug.Log(value55.Count()); //0
34. Contains:序列中是否包含給定的元素
var value56 = array1.Contains(1); Debug.Log(value56); //True
35.1 Count:返回序列中元素的個數(shù)(int)。重載可以添加篩選條件,返回滿足條件的元素個數(shù)
35.2 LongCount:返回序列中元素的個數(shù)(long)。重載可以添加篩選條件,返回滿足條件的元素個數(shù)
var value57 = array1.Count(); Debug.Log(value57); //5 var value58 = array1.LongCount(i => i < 3); Debug.Log(value58); //3
36. Sum:返回序列中值的總和
var value59 = array1.Sum(); Debug.Log(value59); //10
37.1 Min:返回序列中最小的值
37.2 Max:返回序列中最大的值
var value60 = array1.Min(); Debug.Log(value60); //0 var value61 = array1.Max(); Debug.Log(value61); //4
38. Average:返回序列中的平均值
var value62 = array1.Average(); Debug.Log(value62); //2
39. Any:序列中是否存在滿足條件的元素
var value63 = array1.Any(i => i > 0); Debug.Log(value63); //True
40. All:序列中是否全部元素都滿足條件
var value64 = array1.All(i => i > 0); Debug.Log(value64); //False
41. Append:將一個值追加到序列末尾
var value65 = array1.Append(10); TestLog(value65); // - 0 - 1 - 2 - 3 - 4 - 10
42. Aggregate:連續(xù)對序列中的各個元素應(yīng)用給定的函數(shù)
//Aggregate 01 //對序列應(yīng)用累加器函數(shù) 將指定的種子值用作累加器初始值 并使用指定的函數(shù)選擇結(jié)果值 //public static TResult Aggregate<TSource, TAccumulate, TResult>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector); //Aggregate 02 //對序列應(yīng)用累加器函數(shù) 將指定的種子值用作累加器初始值 //public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func); //Aggregate 03 //對序列應(yīng)用累加器函數(shù) //public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func); //TSource : source的元素類型 //TAccumulate : 累加器值的類型 //TResult : 結(jié)果值的類型 //source IEnumerable<TSource> : 要應(yīng)用累加器的序列IEnumerable<T> //seed TAccumulate : 累加器的初始值 //func Func<TAccumulate, TSource, TAccumulate> : 要對每個元素調(diào)用的累加器函數(shù) //resultSelector Func<TAccumulate, TResult> : 將累加器的最終值轉(zhuǎn)換為結(jié)果值的函數(shù) string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" }; //Aggregate 01 Demo 查找長度最長的字符串 string longestName = fruits.Aggregate("banana", (longest, next) => next.Length > longest.Length ? next : longest, fruit => fruit.ToUpper()); Debug.Log("longestName : " + longestName); //Aggregate 02 Demo 查找名字以"e"結(jié)尾的的數(shù)量 int count = fruits.Aggregate(0, (total, next) => next.EndsWith("e") ? total + 1 : total); Debug.Log("count : " + count); //Aggregate 03 Demo 顛倒字符串順序 string sentence = "the quick brown fox jumps over the lazy dog"; // Split the string into individual words. string[] words = sentence.Split(' '); // Prepend each word to the beginning of the new sentence to reverse the word order. string reversed = words.Aggregate((workingSentence, next) => next + " " + workingSentence); Debug.Log("reversed : " + reversed); //累加字典Dictionary的Value Dictionary<string, int> numDic = new Dictionary<string, int>(); int totalNum = numDic.Aggregate(0, (total, next) => total += next.Value);
到此這篇關(guān)于C# System.Linq 萬能的查詢語句的文章就介紹到這了,更多相關(guān)C# System.Linq 查詢語句內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#利用WinForm實現(xiàn)查看指定目錄下所有圖片功能
Windows 窗體是用于生成 Windows 桌面應(yīng)用的 UI 框架, 它提供了一種基于 Visual Studio 中提供的可視化設(shè)計器創(chuàng)建桌面應(yīng)用的高效方法,本文介紹了C#利用WinForm實現(xiàn)可以查看指定目錄文件下所有圖片功能,需要的朋友可以參考下2024-05-05