c# Linq&Lambda

0.寫這個文章主要記錄下經常使用Lambda的用法,能力有限,文中有問題的地方但願各位大神指出來謝謝!由於平時寫代碼的時候沒有特意去用lambda,全是用一些循環,少許會用到lambda,雖然也能實現要的功能,可是代碼量及可讀性就沒那麼好了。因此從新熟悉了一下lambda。對了,此篇文章大部份內容參考了shang神的文章,部份內容本身補充了一些。html

一.經常使用方法及說明ide

1.1 先準備以下類及列表用於實操函數

public class Person
    {
        public int PId { get; set; } //自增ID
        public string Name { get; set; }
        public int Age { get; set; }
        public int JobId { get; set; }
    }
Person
public class Job
    {
        public int JobId { get; set; } //自增ID
        public string JobName { get; set; }
        public int WorkAge { get; set; }
    }
Job
List<Person> pA = new List<Person>();
pA.Add(new Person() { PId = 1, Name = "張三", Age = 16, JobId = 1 });
pA.Add(new Person() { PId = 2, Name = "小紅", Age = 18, JobId = 2 });
pA.Add(new Person() { PId = 3, Name = "王武", Age = 20, JobId = 3 });
pA.Add(new Person() { PId = 4, Name = "小梅", Age = 17, JobId = 4 });
pA.Add(new Person() { PId = 5, Name = "小李", Age = 24, JobId = 3 });        
PersonList
List<Job> jB = new List<Job>();
jB.Add(new Job() { JobId = 1, JobName = "製造業", WorkAge = 3 });
jB.Add(new Job() { JobId = 2, JobName = "IT行業", WorkAge = 5 });
jB.Add(new Job() { JobId = 3, JobName = "建築業", WorkAge = 2 });
jB.Add(new Job() { JobId = 4, JobName = "金融業", WorkAge = 1 });
jBList

1.2 主要操做方法測試

1.2.1 Select(將序列中的每一個元素投影到新表中)this

即當你只是須要序列中每一個元素某個或者某些字段時,可以使用Selectspa

//返回Name字段列表
var result = pA.Select(k => k.Name).ToList();
//加上index,而且返回一個匿名函數
var result0 = pA.Select((k,index) => new { index = index,person = k}).ToList();

result 返回了Name字段的列表 code

result0 返回了一個匿名類的對象列表,匿名類有兩個字段:index(下標),person對象htm

1.2.2 Where(基於謂詞篩選值序列)對象

即篩選序列中符合條件的元素並返回新列表blog

//篩選出Age大於18的記錄
var result1 = pA.Where(k => k.Age > 18).ToList();
//r參數表明元素在集合中的索引
var result112 = pA.Where((k,r) =>
{
    if (r <= 3)
        return false;
    return k.Age > 18;
}
).ToList();

//篩選出Age大於18而且JobId等於3的記錄
var result2 = pA.Where(k => k.Age > 18 && k.JobId==3 ).ToList();

//篩選出Age大於18或者JobId等於3的記錄
var result3 = pA.Where(k => k.Age > 18 || k.JobId == 3).ToList();

result1篩選出Age大於18的記錄

result112篩選出Age大於18而且下標大於3的記錄

result2篩選出Age大於18而且JobId等於3的記錄

result3篩選出Age大於18或者JobId等於3的記錄
1.2.3

Single(返回序列的惟一元素;若是該序列並不是剛好包含一個元素,則會引起異常。)

SingleOrDefault(返回序列中的惟一元素;若是該序列爲空,則返回默認值;若是該序列包含多個元素,此方法將引起異常。)

First(返回序列中的第一個元素。)

FirstOrDefault(返回序列中的第一個元素;若是序列中不包含任何元素,則返回默認值。)

Last(返回序列的最後一個元素。)

LastOrDefault(返回序列中的最後一個元素;若是序列中不包含任何元素,則返回默認值。)

以上這六個方法用法相似,目的都是爲返回一個元素。後綴有Default就是當序列沒有知足條件的元素時,返回爲空。

//返回知足指定條件的元素,若爲空或返回數量不止一個,則拋異常
var result171 = pA.Single(r => r.JobId == 2);
//返回知足指定條件的元素,若爲空,則返回空;若返回數量不止一個,則拋異常
var result172 = pA.SingleOrDefault(r => r.JobId == 2);

//返回知足指定條件的對象列表中的第一個元素,若爲空,則拋異常
var result173 = pA.First(r => r.JobId == 2);
//返回知足指定條件的對象列表中的第一個元素,若爲空,則返回空
var result174 = pA.FirstOrDefault(r => r.JobId == 2);

//返回知足指定條件的對象列表中的最後一個元素,若爲空,則拋異常
var result175 = pA.Last(r => r.JobId == 2);
//返回知足指定條件的對象列表中的最後一個元素,若爲空,則返回空
var result176 = pA.LastOrDefault(r => r.JobId == 2);

1.2.4 

OrderBy(根據鍵按升序對序列的元素排序。)

OrderByDescending(根據鍵按降序對序列的元素排序。)

ThenBy(根據某個鍵按升序對序列中的元素執行後續排序。)

ThenByDescending(根據某個鍵按降序對序列中的元素執行後續排序。)

即對序列進行排序。

//先篩選出Age大於10的記錄,再根據Age列升序/正序輸出
var result6 = pA.Where(k => k.Age > 10)
    .OrderBy(k => k.Age).ToList();

//先篩選出Age大於10的記錄,再按Age倒序,再按JobId正序,再按名稱倒序。
var result8 = pA.Where(k => k.Age > 10).OrderByDescending(k => k.Age)
    .ThenBy(k => k.JobId).ThenByDescending(k => k.Name).ToList();

result6 返回了按照Age字段升序排列的列表

result8 返回了先按照Age字段降序,再按照JobId升序,再按照Name字段降序的列表
1.2.5

GroupBy(根據指定的鍵選擇器函數對序列中的元素進行分組。)

ToDictionary(根據指定的鍵選擇器函數,從 System.Collections.Generic.IEnumerable`1 建立一個 System.Collections.Generic.Dictionary`2。)

GroupBy能夠對序列進行分組,ToDictionary能夠將序列轉成字典。

var result4 = pA.Where(k => k.Age > 10).GroupBy(j => j.JobId).Select(l => l.Key).ToList();
var result41 = pA.Where(k => k.Age > 10).GroupBy(j => j.JobId);
var result42 = result41.ToDictionary(r => r.Key);
var result43 = result41.ToDictionary(r => r.Key,rr=>rr.Select(r=>r.Name));
var result5 = pA.Where(k => k.Age > 10)
    .GroupBy(a => new Person { PId = a.PId, Name = a.Name, Age = a.Age, JobId = a.JobId })
    .Select(a => a.Key).ToList();

result4先篩選出Age大於10的元素,再根據JobId字段分組(分組的字段即爲Key),再選擇鍵(Key)返回

result41先篩選出Age大於10的元素,再根據JobId字段分組(分組的字段即爲Key)

result42在result41的基礎上將分組後內容轉成字典,鍵選擇了分組時的Key,值默認是分組時的element

result43在result41的基礎上將分組後內容轉成字典,鍵選擇了分組時的Key,值選擇了分組時的element中的Name字段

result5先篩選出Age大於10的元素,再根據Persson對象分組,再選擇鍵(Key)返回(此處的key爲Person對象)

1.2.6 Average,Sum,Min,Max(平均值/求和/最大值/最小值)

//獲取Age的平均值
var result10 = pA.Average(k => k.Age);

//獲取Age的平均值
var result101 = pA.Sum(k => k.Age);

var result201 = pA.Min(r => r.Age);
var result202 = pA.Max(r => r.Age);

1.2.7 

All(肯定序列中的全部元素是否知足條件。)

Any(肯定序列是否包含任何元素。/肯定序列是否包含知足條件的元素。)

var result211 = pA.All(r => r.Age > 18);
var result212 = pA.Any(r => r.Age > 18);
var result213 = pA.Any();

result211中只有PA列表全部元素的Age大於18,才返回True

result212中PA列表任一元素的Age大於18,即返回True

result213中PA列表不爲空時返回True
1.2.8 Repeat(生成包含一個重複值的序列。)

var result191 = Enumerable.Repeat(pA.First(), 10);

result191 返回了有十條pA.First()元素的序列
1.2.9 

Cast(將 System.Collections.IEnumerable 的元素強制轉換爲指定的類型。)

OfType(根據指定類型篩選 System.Collections.IEnumerable 的元素。)

var result221 = pA.Cast<object>();
var result222 = pA.OfType<Job>();

result221中將pA序列中全部元素強轉成object類型(實際使用應該會轉其餘類型)

result222從pA序列中篩選出類型爲Job的元素並返回
1.2.10 

Take(從序列的開頭返回指定數量的連續元素。)

TakeWhile(只要知足指定的條件,就會返回序列的元素。)

Skip(跳過序列中指定數量的元素,而後返回剩餘的元素。)

SkipWhile(只要知足指定的條件,就跳過序列中的元素,而後返回剩餘元素。)

//先篩選出Age大於10的記錄,再取前三條記錄
var result154 = pA.Where(o => o.Age > 10).Take(3).ToList();
//從index=0開始,若符合條件,則取出並繼續下一個,不然。中止。(與Where不一樣)
var result155 = pA.TakeWhile(k => k.Age > 18).ToList();
var result156 = pA.TakeWhile((k, index) => index < 2).ToList();

var result161 = pA.Skip(2);
//從index=0開始,若符合條件,則跳過該繼續下一個,不然。中止。
var result162 = pA.SkipWhile(r => r.JobId == 3);
var result163 = pA.SkipWhile((r,index) => index <= 3);

result154先篩選出Age大於10的記錄,再取前三條記錄

result155從pA序列的index=0開始,若元素符合條件(此處是Age大於18),則取出並繼續下一個判斷,不然,中止判斷並返回以前取出符合條件的元素。(與Where不一樣)

result155從pA序列的index=0開始,若元素符合條件(此處是index小於2),則取出並繼續下一個判斷,不然,中止判斷並返回以前取出符合條件的元素。(與Where不一樣)

result161 先跳過pA前兩個元素,再返回剩下的序列

result162從pA序列的index=0開始,若元素符合條件(此處是JobId等於3),則跳過該元素並繼續下個元素的判斷。不然,中止判斷並返回當前元素以及剩下元素的序列。

result162從pA序列的index=0開始,若元素符合條件(此處是index小於3),則跳過該元素並繼續下個元素的判斷。不然,中止判斷並返回當前元素以及剩下元素的序列。

1.2.11 Join(基於匹配鍵對兩個序列的元素進行關聯。使用默認的相等比較器對鍵進行比較。)

var result12 = pA.Join(jB, j => j.JobId, k => k.JobId, (j, k) => new { j.PId, j.Name, j.Age, k.JobName }).ToList();

pA和jB分別是兩個須要進行鏈接的序列,關聯的字段爲pA的JobId和jB的JobId字段,返回一個匿名類對象,包含pA的PId,Name,Age和jB的JobName字段

1.2.12 SelectMany(將序列的每一個元素投影到 System.Collections.Generic.IEnumerable`1 並將結果序列合併爲一個序列。)

public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);

public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector);

public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);

//返回的是IEnumerabele<string>類型
var result181 = pA.SelectMany(r => new List<string>()
{
    r.Name,
    r.Age.ToString()
});
var result182 = pA.SelectMany((r,index) => new List<string>()
{
    r.Name,
    r.Age.ToString(),
    index.ToString()
});
//返回結果爲List<object>,其中r爲Person類,rr爲第一步返回的 List<string>
var result183 = pA.SelectMany(r => new List<string>()
{
    r.Name,
    r.Age.ToString()
},(r,rr) => new List<object>
{
    r.JobId,
    rr
});

result181 返回的序列中將會把原始序列中每一個元素的Name和Age字段單獨造成一個元素並返回,即新序列的長度爲原始序列長度的兩倍。

result182 返回的序列中將會把原始序列中每一個元素的index,Name和Age字段單獨造成一個元素並返回,即新序列的長度爲原始序列長度的三倍。

result183 方法中第一個參數與result181 相同,第二個參數將原始序列中的元素和第一個參數返回的序列中的元素做爲新參數,返回新的序列。

二.總結Linq這個東西其實挺好用的,要是用的好能夠大大優美代碼且減小代碼量。還有一些複雜的方法沒有講到,等下次再寫。有什麼不足的地方但願大神提出來我會改之。

測試代碼地址以下:Linq_Lambada

相關文章
相關標籤/搜索