DAY 23 LINQ 查詢運算式(二)

LINQ

來繼續簡單介紹 LINQ 的功能吧。

Take & Skip

這兩種都是對集合內的元素依排序操作的方法,所以使用前通常會先 OrderBy,以下四種方法都是給予一個 int 引數,若 int 大於集合數量也不會產生錯誤。

Take

Take 集合現有排序中取出前幾個元素,如

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var scoresTakeTop3 = scores.Take (3);

TakeLast

TakeLast 集合現有排序中取出後幾個元素,元素排序依照原排序,如

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var scoresTakeLast3 = scores.TakeLast (3);

Skip

Skip 集合現有排序中跳過幾個元素後取出,如

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var scoresSkipTop3 = scores.Skip (3);

SkipLast

SkipLast 集合現有排序中跳過後幾個元素後取出,如

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var scoresSkipLast3 = scores.SkipLast (3);

First & Single

這兩種都是使集合傳回一筆元素的方法。

First

First 取出集合內的第一筆元素,或添加 Predicate 的多載方法,如

1
2
3
int[] scores = new int[] { 97, 92, 81, 60 };
var scoresFirst = scores.First ();
var scoresFirstLessThan90 = scores.First (x => x < 90);

但是,如果集合是空集合或者集合內並無任何一筆符合則會報錯,我們則需改用以下方式

FirstOrDefault

FirstOrDefault 當集合內取不出第一筆元素時,則傳回 default (T),一樣有有無添加 Predicate 的兩種多載方法。

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var scoresFirstMoreThan900 = scores.FirstOrDefault (x => x > 900);

Single

Single 如果集合內的元素不是一筆則會報錯,一樣有兩種多載方法。

1
2
3
int[] scores = new int[] { 97, 92, 81, 60 };
var score = scores.Single (); // 錯誤示範
var scoreMoreThan95 = scores.Single (x => x > 95);

也有相對應的傳回泛型預設值版本

SingleOrDeafault

SingleOrDeafault 如果集合內的元素大於一筆則會報錯,空集合則會傳回泛型預設值,一樣有兩種多載方法。

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var score = scores.SingleOrDefault (x => x > 900);

Any & All & Contains

這三種都是檢查集合內元素的方法,並傳回 bool。

Any

Any 檢查有無任何一個元素符合條件,但不加任何 Predicate 則代表檢查是否空集合,如

1
2
3
int[] scores = new int[] { 97, 92, 81, 60 };
var isScoresAny = scores.Any ();
var isScoresAnyMoreThan77 = scores.Any (x => x > 77);

All

All 檢查集合內元素皆符合條件,因為一定要有條件,所以這個方法沒有無 Predicate 的方法,如

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var isScoresAllMoreThan70 = scores.All (x => x > 70);

Contains

Contains 是檢查集合內是否擁有某個相同類型的元素,如

1
2
int[] scores = new int[] { 97, 92, 81, 60 };
var scoresContains900 = scores.Contains (900);

因為比較的不是集合本身,而是外部的物件,所以本來是不想放在這裡,但考量傳回值都是 bool,所以放到最後面並說明差異。

Join

Join 是將兩個集合合併成一個新集合,如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int[] scores = new int[] { 97, 92, 81, 60 };

var members = new List<Member> () {
new Member () { ID = 0, Name = "Mio" },
new Member () { ID = 1, Name = "Miffy" },
new Member () { ID = 2, Name = "Lulu" },
new Member () { ID = 3, Name = "NekoSan" }
};

var scoresAddNo = scores
.Select ((x, y) => new { score = x, No = y });

var scoresJoinMember = scoresAddNo
.Join (members,
score => new { ID = score.No },
member => new { ID = member.ID },
(score, member) => new {
ID = score.No,
Name = member.Name,
Score = score.score
});

合併時,要注意傳入的值若為 null 就會報錯,那這邊就來講解一下引數作用。

第一個當然就是欲合併的集合。

第二個則是傳入合併的集合元素並給出任意類型的 Join Key。

第三個則是傳入欲合併的集合並給出與第二個 Join Key 一樣類型的 Join Key,我這邊雖然只有一個 Key,但寫成相同的匿名類型,在日後使用時疑問不會這麼多。當然如同前面所說 score 與 member 這名稱都可以自己替換。

第四個則是傳回的新集合,傳入合併與欲合併的集合,並傳回想要的成員。

GroupBy

GroupBy 是將集合依照相關成員進行分群,如

1
2
3
4
5
6
7
8
var members = new List<Member> () {
new Member () { ID = 0, Name = "Mio" },
new Member () { ID = 1, Name = "Miffy" },
new Member () { ID = 2, Name = "Lulu" },
new Member () { ID = 3, Name = "NekoSan" }
};

var membersGroupByFirstChar = members.GroupBy (x => x.Name.First ());

可以看到總共分成三個 L、M、N 開頭的群組, M 群裡面有兩個集合,其他則是一個,而當成分群條件的則變成該群的 Key,所以這邊示範一下

1
2
3
4
5
6
7
8
9
10
11
12
13
var members = new List<Member> () {
new Member () { ID = 0, Name = "Mio" },
new Member () { ID = 1, Name = "Miffy" },
new Member () { ID = 2, Name = "Lulu" },
new Member () { ID = 3, Name = "NekoSan" }
};

foreach (var group in members.GroupBy (x => x.Name.First ())) {
Console.WriteLine (group.Key);
foreach (var member in group) {
Console.WriteLine ($"\tID = {member.ID}, Name = {member.Name}");
}
}

一些小結論

今天大致把比較常用的 LINQ 方法介紹完,當然還有很多東西沒提到,但 LINQ 的部分就到這裡了,當然其他方法想討論也可以在下面留言唷。

感謝閱讀。