別再眼高手低了! 這些Linq方法都清楚地掌握了嗎?

jason發表於2020-09-12

不要再眼高手低了,這些Enumerable之常見Linq擴充套件方法都清楚掌握了嗎?其實這是對我自己來說的!

例如:一個人這個技術掌握了一點那個技術也懂一點,其他的好像也瞭解一些,感覺自己啥都會一點,又覺得自己啥都不會!

好像是處於那種技術瘋癲的症態中!獨孤求敗!其實主要還是不願意動手實踐一下,總是會對低的技術看不上,高的技術又學不懂,或者是半懂不懂,或者是堅持不下去等等,

這些都是不可取的,加油吧騷年!

步入正軌:

1:什麼是Linq(下面專業的名詞解釋參考來自於網路以及官網的文件,點選這裡)

   1.1:LINQLanguage Integrated Query的簡稱,它是整合在.NET程式語言(例如:C#、VB.NET等)中的一種特性,目的是為.NET Framework提供更加通用和便利的資訊查詢方式,

    並且它對資料來源提供了廣泛的支援,而不僅僅侷限於關係型資料庫和XML。

  1.2:LINQ定義了一組標準查詢操作符用於在所有基於.NET平臺的程式語言中更加直接地宣告跨越、過濾和投射操作的統一方式,標準查詢操作符允許查詢作用於所有基於IEnumerable介面的源,

    比如Array,List,XML,DOM或者是SQL Server資料表。並且它還允許適合於目標域或技術的第三方特定域操作符來擴大標準查詢操作符集,更重要的是,第三方操作符可以用它們自己的提供附加服務的實現來自由地替換標準查詢操作符,

    根據LINQ模式的習俗,這些查詢喜歡採用與標準查詢操作符相同的語言整合和工具支援

 2:使用Linq有啥好處

   2.1:使用LINQ的目的是為了提供一個解決物件關係對映問題的方案,同時簡化物件和資料來源的互動。LINQ最終發展成為一個通用語言整合查詢的工具包。

  2.2:LINQ正如它的名字“整合查詢語言”的含義一樣,它提供給程式設計師一個統一的程式設計介面。程式設計師不需要關心他將要操作的將是關聯式資料庫還是XML,

    甚至是遠端的物件,它都採用同樣的查詢方式。就如同通過T-SQL操縱資料庫一樣,不管是OracleSyBase還是SQL Server,他們的Select語法都是一樣的。

  2.3:有了LINQ,程式設計師便可以不再沉泥於不同的資料訪問技術的學習。不管程式語言如何發展,還是資料庫技術的發展,都不再需要程式設計師進行學習,

    資料儲存的效率由資料庫廠商進行優化,靈活的資料操作方法由資料訪問中介軟體廠商提供,程式設計師只需要編寫業務邏輯,

  2.4:提升開發效率等

3:C# Linq類庫

  在C#中,LINQ相關類庫都在System.Linq名稱空間下。該名稱空間提供支援使用LINQ進行查詢的類和介面,其中最重要的是兩個類和兩個介面。

  IEnumerable介面:它表示可以查詢的資料集合,一個查詢通常是逐個對集合中的元素進行篩選操作,返回一個新的IEnumerable物件,用來儲存查詢結果。

  IQuerable介面:它繼承IEumerable介面,表示一個可以查詢的表示式目錄樹。

  Enumerable類,它通過對IEnumerable提供擴充套件方法,實現LINQ標準查詢運算子。包括過濾、導航、排序、查詢、聯接、求和、求最大值、求最小值等操作。

  Queryable類:它通過對IQueryable提供擴充套件方法,實現LINQ標準查詢運算子。包括過濾、導航、排序、查詢、聯接、求和、求最大值、求最小值等操作

這裡我想說的是:記住只一點就不會搞混淆:IQueryable通常是查詢運算元據庫中的資料,IEnumerable通常是處理記憶體中的資料

4:Linq 的種類

  根據資料來源型別,可以將LINQ技術分成如下所述的3個主要技術方向。
  1:LINQ to Objects 資料來源為實現了介面IEnumerable或IQeryable的記憶體資料集合,這也是LINQ的基礎。
  2:LINQ to XML 資料來源為XML文件,這裡通過XElement、XAttribute等類將XML文件資料載入到記憶體中,通過LINQ進行資料查詢。
  3:LINQ to ADO.Net 

想進一步瞭解上面的幾種型別的使用,大家可以參考網路上的資源(比較多,這裡就不再展示了)謝謝!

5:Core3.1下面的Linq有哪些常見的擴充套件方法,怎麼使用?如下簡單的demo案例:

  Aggregate 的使用

  {
                List<int> listnum = new List<int>();
                for (int i = 1; i <= 100; i++)
                {
                    listnum.Add(i);
                }
                //Aggregate 總數;合計
                var getAggregateData = listnum.Aggregate((a, b) =>
                  {
                      return a + b;
                  });
                Console.WriteLine("從1+2+3+**100={0}", getAggregateData);

                //Aggregate 求偶數的個數 0:表示從0開始; totalCount:記錄總的次數; gonumber:要依次遍歷的元素
                int gettotalcount = listnum.Aggregate(0, (totalCount, gonumber) =>
                   {
                       return gonumber % 2 == 0 ? totalCount += 1 : totalCount;
                   });
                Console.WriteLine("偶數的個數有:{0}個", gettotalcount);
  }

 

All 的使用 需要所有的條件都滿足才行,只要有一個條件不滿足就不會再執行下去

明明有兩隻豬都滿足條件,單數只查詢到老豬的資料 是不是和起初想的不一樣呢?其實想想才恍然大悟 all的含義就是全部的意思,

這裡只要不滿足條件就沒有必要再往下面去查詢了,起到提升效率的作用

{
                List<Pig> pigs = new List<Pig> {
                    new Pig{ pid="Z003",name="老豬",age=10},
                    new Pig{ pid="Z001",name="小豬",age=1},
                    new Pig{ pid="Z002",name="青年豬",age=3},
                    new Pig{ pid="Z004",name="八戒",age=500},
                };
                var newlist = new List<Pig>();
                var pigallConditionok = pigs.All(p =>
                {
                    if (p.age >= 10)
                    {
                        newlist.Add(p); return true;
                    }
                    else { return false; }
                });
                Console.WriteLine(pigallConditionok ? "所有的豬都滿足大於10歲" : "不是所有的豬都滿足大於10歲");
                Console.WriteLine($"所有的豬都滿足大於10歲的名稱有:{string.Join(", ", newlist.Select(c => c.name))},其年齡分別為:{string.Join(", ", newlist.Select(c => c.age))}");            

 

 Any 的使用 ,來確定集合是否包含任何元素

List<Pig> pigs = new List<Pig> {
                new Pig{ pid="Z003",name="老豬",age=10},
                new Pig{ pid="Z001",name="小豬",age=1},
                new Pig{ pid="Z002",name="青年豬",age=3},
                new Pig{ pid="Z004",name="八戒",age=500},
            };
            var newlist = new List<Pig>();
            if (pigs != null && pigs.Any())
            {
                newlist = pigs.Where(c => c.age >= 10).ToList();
                Console.WriteLine($"所有的豬都滿足大於10歲的名稱有:{string.Join(", ", newlist.Select(c => c.name))},其年齡分別為:{string.Join(", ", newlist.Select(c => c.age))}");
            }
            else
            {
                Console.WriteLine("沒有資料!");
            }

 Append的使用 將值追加到序列的末尾。 此方法不修改集合中的元素。 相反,它使用新元素建立集合的副本

List<string> liststr = new List<string> { "你好", ":" };
            liststr.Append("帥哥");
            Console.WriteLine(string.Join(" ", liststr));
            Console.WriteLine("啥,為啥沒有效果???");
            Console.WriteLine(string.Join(" ", liststr.Append(Console.ReadLine())));
            Console.WriteLine("你可以說一些肉麻的話:");
            Console.WriteLine(string.Join(" ", liststr.Append(Console.ReadLine())));

 

 AsEnumerable的使用 返回型別化為 IEnumerable<T> 的輸入

 MyDog<string> mydog = new MyDog<string> { "absdsdsd", "grgrfefs", "wqethh", "mhngf" };

            //直接使用指定的委託非法MyWhere() 我們想查詢集合中包含 s的元素有哪些
            var newlistMywhere = mydog.MyWhere(c => c.Contains('s')).ToList();

            //AsEnumerable() 後 會隱藏MyDog自定義的MyWhere方法,而是使用Linq系統自帶的where方法
            var newlistLinqWhere = mydog.AsEnumerable().Where(c => c.Contains("s"));

            Console.WriteLine(string.Join(" ; ", newlistMywhere));
            Console.WriteLine(string.Join(" | ", newlistMywhere));

 

 Average的使用  計算數值序列的平均值。比較簡單的使用

IEnumerable<decimal> list = new List<decimal> { 88, 70, 90, 60, 85, 100 };
            decimal avgScore = list.Average();
            Console.WriteLine("平均分是(保留小數點後兩位數):" + Math.Round(avgScore, 2));

 

Cast的使用 將 IEnumerable 的元素強制轉換為指定的型別

ArrayList arlist = new ArrayList { "99", "88", "100" };
            var newlist = arlist.Cast<string>().OrderByDescending(c => c).Select(c => c.ToString()).ToList();
            Console.WriteLine("強轉前: " + string.Join(" ", arlist));
            Console.WriteLine("強轉之後: " + string.Join(" ", newlist));

 

Concat的使用連線兩個序列

 List<Pig> list01 = new List<Pig> { new Pig { name = "八戒" }, new Pig { name = "喜歡" } };
            List<Pig> list02 = new List<Pig> { new Pig { name = "嫦娥仙女" }, new Pig { name = "也去過高老莊" } };

            var listname = list01.Select(c => c.name).Concat(list02.Select(a => a.name));
            Console.WriteLine(string.Join(", ", listname));

 

Contains的使用 確定序列是否包含指定的元素。

  List<string> list = new List<string> { "小豬", "青年豬", "老豬", "八戒" };
            if (list.Contains("八戒"))
            {
                Console.WriteLine("八戒藏在高老莊");
            }
            else { Console.WriteLine("不知八戒的去向"); }

 

Count的使用 返回序列中的元素數量

 List<string> list = new List<string> { "小豬", "青年豬", "老豬", "八戒" };
            Console.WriteLine(list.Count);

 

DefaultIfEmpty 返回 IEnumerable<T> 的元素;如果序列為空,則返回一個具有預設值的單例類集合。

 List<Pig> list = new List<Pig> {
                      new Pig{pid="p001",name="小豬",age=1 },
                      new Pig{pid="p002",name="青年豬",age=2 },
                      new Pig{pid="p003",name="老豬",age=10 },
                      new Pig{pid="p004",name="八戒",age=500 },

            };
            var newlist = list.Where(c => c.age > 500).ToList().DefaultIfEmpty().ToList();
            var newlist2 = list.Where(c => c.age > 500).ToList().DefaultIfEmpty<Pig>(list.Last()).ToList();

            Console.WriteLine(string.Join(", ", newlist.Select(c => c == null ? "沒有找到實體資料" : c.name)));
            Console.WriteLine(string.Join(", ", newlist2.Select(c => c.name)));

 

Distinct的使用 返回序列中的非重複元素。 比較簡單和好理解吧,寶寶們!

 List<string> list = new List<string> { "小豬", "青年豬", "老豬", "八戒", "青年豬", "老豬", };
            Console.WriteLine("獲取到不重複的元素有:" + string.Join(",", list.Distinct()));

 

ElementAt的使用 返回序列中指定索引處的元素

 public static TSource ElementAt<TSource>(this System.Collections.Generic.IEnumerable<TSource> source, int index);
            List<string> list = new List<string> { "小豬", "青年豬", "老豬", "八戒", "青年豬", "老豬", };

            Console.WriteLine("ElementAt是從零開始的,集合第4個元素是{0}", list.ElementAt(3));

 

ElementAtOrDefault的使用 返回序列中指定索引處的元素;如果索引超出範圍,沒有發現會拋異常。

 List<string> list = new List<string> { "白菜", "蘿蔔", "蕃茄", "茄子" };
            string getstr = list.ElementAtOrDefault(5);
            if (!string.IsNullOrEmpty(getstr))
                Console.WriteLine("我比較喜歡吃的蔬菜是:" + getstr);
            else
                Console.WriteLine("超出選擇的範圍,系統為您選擇了一個蔬菜,是:" + list.ElementAtOrDefault(3));

 

 Empty的使用  返回具有指定型別引數的空 IEnumerable<T>,通常我們後端些Core WebApi 介面的時候。

//前端會要求沒有資料幫忙返回空的陣列,不要返回null,這時 Empty就可以很好的上任,也不容易跑出空指標類似的錯誤

 List<Pig> list = new List<Pig> {
                    new Pig{pid="p001",name="小豬",age=1 },
                    new Pig{pid="p002",name="青年豬",age=2 },
                    new Pig{pid="p003",name="老豬",age=10 },
                    new Pig{pid="p004",name="八戒",age=500 }
            };
            //Enumerable.Empty<Pig>().ToList(); 會返回一個空的集合
            var newList = list.Where(c => c.age > 500).ToList() ?? Enumerable.Empty<Pig>().ToList();
            if (newList.Any() || newList.Count > 0)
                Console.WriteLine("有元素在集合中!");
            else
                Console.WriteLine("沒有元素在集合中!");

 

Except的使用  生成兩個序列的差集

 List<int> list01 = new List<int> { 88, 66, 99, 58, 85, 69 };
            List<int> list02 = new List<int> { 78, 22, 69, 80, 88 };

            var newlist01 = list01.Except(list02);
            var newlist02 = list02.Except(list01);

            Console.WriteLine("以list01為準: " + string.Join(", ", newlist01));
            Console.WriteLine("以list02為準: " + string.Join(", ", newlist02));

 

First、FirstOrDefault 的使用返回序列中的第一個元素 如果 source 不包含任何元素,則該方法將引發異常。

 //若要改為在源序列為空時返回預設值,請使用 FirstOrDefault 方法。

 int[] numbers = { 9, 34, 65, 92, 87, 435, 3, 54 };
            int first = numbers.First();
            Console.WriteLine("第一個是:" + first);
            Console.WriteLine("大於500的是:" + numbers.FirstOrDefault(c => c > 500));//帶條件篩選

 

Group 的使用 分組,這個相對於其他已經簡紹的Linq方法稍微複雜些,

List<Person> plist = new List<Person> {
                new Person{ Name="小張",Age=22,Country="中國",Sex=""},
                new Person{ Name="小鄭",Age=21,Country="中國",Sex=""},
                new Person{ Name="Zhang",Age=32,Country="English",Sex=""},
                new Person{ Name="Jason",Age=29,Country="English",Sex=""},
                new Person{ Name="Luce",Age=21,Country="USA",Sex=""},
                new Person{ Name="Peter",Age=22,Country="English",Sex=""},
                new Person{ Name="Tom",Age=32,Country="English",Sex=""},
                new Person{ Name="小紅",Age=28,Country="中國",Sex=""},
                new Person{ Name="小鐘",Age=31,Country="中國",Sex=""}
            };

           // 按照國家來分組 1

            var plistGroupByCountry = plist.GroupBy(c => c.Country).Select(c => c).ToList();
            for (int i = 0; i < plistGroupByCountry.Count; i++)
            {
                string key = plistGroupByCountry[i].Key;
                Console.WriteLine($"按照【key={key}分組】下面對應的具體資訊有:");
                var obj = plistGroupByCountry[i].ToList();
                Console.WriteLine("key=" + key + ",==>" + string.Join(",", obj.Select(c => c.Name)));
                Console.WriteLine();
            }

            //按照國家以及性別來分組 2
            var plistGroupByCountry = plist.GroupBy(c => new { c.Country, c.Sex }).Select(c => c).ToList();
            for (int i = 0; i < plistGroupByCountry.Count; i++)
            {
                string key1 = plistGroupByCountry[i].Key.Country;
                string key2 = plistGroupByCountry[i].Key.Sex;

                Console.WriteLine($"按照【key={key1}和{key2}分組】下面對應的具體資訊有:");
                var obj = plistGroupByCountry[i].ToList();
                Console.WriteLine("國家分別是:" + string.Join(",", obj.Select(c => c.Country)) + "," + "姓名分別是:" + string.Join(",", obj.Select(c => c.Name)) + "性別分別是:" + string.Join(",", obj.Select(c => c.Sex)));
                Console.WriteLine();
            }

            //按照linq to object方法來分組 3
            var newlist = (from g in plist
                           group g by new { g.Country, g.Sex } into d
                           select new
                           {
                               d.Key.Country,
                               d.Key.Sex,
                               totalCountryCount = d.Count()
                           }).ToList();
            if (newlist != null && newlist.Any())
            {
                for (int i = 0; i < newlist.Count; i++)
                {
                    string key_country = newlist[i].Country;
                    string key_sex = newlist[i].Sex;
                    var groupobj = plist.Where(c => c.Country == key_country && c.Sex == key_sex).ToList();
                    if (groupobj != null && groupobj.Any())
                    {
                        Console.WriteLine("============Country:{0}===Sex:{1}====================", key_country, key_sex);
                        for (int y = 0; y < groupobj.Count; y++)
                        {
                            Console.WriteLine("name:" + groupobj[y].Name + ", age=" + groupobj[y].Age + ", Country=" + key_country + ", Sex=" + key_sex);
                        }
                    }
                    Console.WriteLine();
                }
            }
            Console.WriteLine();

            //Linq的Group 分組進一步延伸,來獲取更多的資訊
            var newlist = (from g in plist
                           group g by new { g.Country, g.Sex } into d
                           select new
                           {
                               d.Key.Country,
                               d.Key.Sex,
                               totalCountryCount = d.Count(),
                               maxAge = d.Max(c => c.Age),
                               minAge = d.Min(c => c.Age),
                               sumAge = d.Sum(c => c.Age),
                               //獲取更多的資訊,不止只有 max,min,sum,avg那些聚合函式
                               info = (from t in d
                                       join c in plist on new { t.Country, t.Sex } equals new { c.Country, c.Sex } into tgdata
                                       from td in tgdata.DefaultIfEmpty()
                                       select new { td.Name, td.Age }).Distinct().ToList()
                           }).ToList();
            for (int g = 0; g < newlist.Count; g++)
            {
                string country = newlist[g].Country; string Sex = newlist[g].Sex;
                int totalCountryCount = newlist[g].totalCountryCount;
                int maxAge = newlist[g].maxAge; int minAge = newlist[g].minAge; int sumAge = newlist[g].sumAge;
                var info = newlist[g].info;
                Console.WriteLine("============{0}======{1}==============", country, Sex);
                for (int i = 0; i < info.Count; i++)
                {
                    string name = info[i].Name;
                    int age = info[i].Age;
                    Console.WriteLine($"country={country},Sex={Sex},totalCountryCount={totalCountryCount},maxAge={maxAge},minAge={minAge},sumAge={sumAge},name={name},age={age}");
                }
                Console.WriteLine();
            }

 

 GroupJoin的使用 基於鍵值等同性將兩個序列的元素進行關聯,並對結果進行分組

 /*
             public static System.Linq.IQueryable<TResult> GroupJoin<TOuter,TInner,TKey,TResult> (this System.Linq.IQueryable<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Linq.Expressions.Expression<Func<TOuter,TKey>> outerKeySelector, System.Linq.Expressions.Expression<Func<TInner,TKey>> innerKeySelector, System.Linq.Expressions.Expression<Func<TOuter,System.Collections.Generic.IEnumerable<TInner>,TResult>> resultSelector);
             */

            List<Student> stulist = new List<Student> {
                new Student{ sid="S001",sName="小張",bookid="bk001"},
                new Student{ sid="S002",sName="小劉",bookid="bk002"},
                new Student{ sid="S003",sName="小鄭",bookid="bk003"},
                new Student{ sid="S004",sName="小李",bookid="bk004"},
                new Student{ sid="S005",sName="小趙",bookid="bk002"},
                new Student{ sid="S006",sName="小王",bookid="bk005"}
            };
            List<Book> blist = new List<Book> {
                new Book{ bid="bk001",bName="西遊記"},
                new Book{ bid="bk002",bName="紅樓夢"},
                new Book{ bid="bk003",bName="三國演義"},
                new Book{ bid="bk004",bName="天龍八部"},
                new Book{ bid="bk005",bName="笑傲江湖"}
            };
            var groupjoinList = stulist.GroupJoin(blist, s => s.bookid, b => b.bid, (s, _bist) => new
            {
                s.sid,
                s.sName,
                //  必需要有一個欄位來接收
                booksInfo = _bist.Select(b => new
                {
                    b.bid,
                    b.bName
                }).ToList()
            }).ToList();

            for (int i = 0; i < groupjoinList.Count; i++)
            {
                string sid = groupjoinList[i].sid;
                string sname = groupjoinList[i].sName;
                var bookinfo = groupjoinList[i].booksInfo;
                Console.WriteLine("======={0}=={1}==========", sid, sname);
                for (int b = 0; b < bookinfo.Count; b++)
                {
                    string bid = bookinfo[b].bid;
                    string bname = bookinfo[b].bName;
                    Console.WriteLine($"sid={sid},sname={sname},bid={bid},bname={bname}");
                }
                Console.WriteLine();
            }

Intersect的使用 生成兩個序列的交集,這個比較簡單,很好理解

int[] list01 = { 10, 2, 58, 66, 30, 24, 56 };
            int[] list02 = { 22, 30, 86, 50, 10, 99, 64, 32, 45, 2 };

            var newlist = list01.Intersect(list02);
            foreach (var item in newlist)
                Console.WriteLine($"交集有:{item}");

            Console.WriteLine("====================");
            List<Book> blist001 = new List<Book> {
                new Book{ bid="bk001",bName="西遊記"},
                new Book{ bid="bk002",bName="紅樓夢"},
                new Book{ bid="bk003",bName="三國演義"},
                new Book{ bid="bk004",bName="天龍八部"},
                new Book{ bid="bk005",bName="笑傲江湖"}
            };
            List<Book> blist002 = new List<Book> {
                new Book{ bid="bk001",bName="西遊記"},
                new Book{ bid="bk002",bName="紅樓夢"},
                new Book{ bid="bk003",bName="三國演義"}
            };
            var newbookList = blist001.Intersect(blist002);
            if (newbookList != null && newbookList.Any())
            {
                foreach (var bookinfo in newbookList)
                    Console.WriteLine($"交集有:bid={bookinfo.bid},bName={bookinfo.bName}");
            }
            else
            {
                Console.WriteLine("沒有找到,原因:是不相同的Book物件,值相同也是不行的!");
            }
            Console.WriteLine("======我們 可以通過如下方法來查詢到相同的交集==============");

            var haveSameEntityList = blist001.Where(c => blist002.Exists(q => q.bid == c.bid)).ToList();
            foreach (var item in haveSameEntityList)
                Console.WriteLine($"交集有:bid={item.bid},bName={item.bName}");

 

Join的使用 這個我們是經常使用到的,多個集合聯合查詢 基於匹配鍵對兩個序列的元素進行關聯。相對於SQL中的多表聯合查詢,只是內連線的效果

/*
             Join<TOuter,TInner,TKey,TResult>(IQueryable<TOuter>, IEnumerable<TInner>, Expression<Func<TOuter,TKey>>, Expression<Func<TInner,TKey>>, Expression<Func<TOuter,TInner,TResult>>)
             */
            List<Book> bleft = new List<Book> {
                new Book{ bid="bk001",bName="西遊記"},
                new Book{ bid="bk002",bName="紅樓夢"},
                new Book{ bid="bk003",bName="三國演義"},
                new Book{ bid="bk004",bName="天龍八部"},
                new Book{ bid="bk005",bName="笑傲江湖"}
            };
            List<Book> bright = new List<Book> {
                new Book{ bid="bk001",bName="西遊記"},
                new Book{ bid="bk002",bName="紅樓夢"},
                new Book{ bid="bk003",bName="三國演義"}
            };
            //想象一想是:左連線
            var _Llist = bleft.Join(bright, L => L.bid, R => R.bid, (L, R) => new { L.bid, L.bName }).ToList();
            foreach (var item in _Llist)
                Console.WriteLine($"左連線:bid={item.bid},bName={item.bName}");
            Console.WriteLine("===================");
            //想象一想是:右連線,我們交換一下位置看看
            var Rlist = bright.Join(bleft, L => L.bid, R => R.bid, (L, R) => new { R.bid, R.bName }).ToList();
            foreach (var item in Rlist)
                Console.WriteLine($"右連線:bid={item.bid},bName={item.bName}");
            //內連線
            Console.WriteLine("從上面的結果可以看出 join就是內連線的效果,那左右連線要怎麼實現???告示寶寶,答案!");
            //請參考個人裡外一遍筆記,這裡就不在重複列出:參考地址: https://www.cnblogs.com/Fengge518/p/13543250.html

 

Last的使用 返回序列中的最後一個元素。使用起來還是比較簡單!

  int[] listint = { 66, 55, 2, 88, 10, 8, 62, 5, 66, 47, 65 };
                int last = listint.Last();
                Console.WriteLine("最後一位是:" + last);

 

LastOrDefault的使用 返回序列中的最後一個元素;如果未找到該元素,則返回預設值,測試同上

 int[] listint = { 66, 55, 2, 88, 10, 8, 62, 5, 66, 47, 65 };
                int last = listint.LastOrDefault();
                int newlast = listint.Where(c => c > 1000).LastOrDefault();
                Console.WriteLine("last最後一位是:" + last);
                Console.WriteLine("newlast最後一位是:" + newlast);

Reverse 的使用 反轉序列中元素的順序。

 List<string> liststr = new List<string> { "I", "Love", "You" };
            Console.WriteLine(string.Join(" ", liststr));
            Console.WriteLine("===========開始反轉===========");
            liststr.Reverse();
            Console.WriteLine(string.Join(" ", liststr));

 

Repeat的使用 生成包含一個重複值的序列。我們可以從字面上猜出,重複的含義

   IEnumerable<string> repeatStr = Enumerable.Repeat("我熱愛學習!", 6);
            foreach (var item in repeatStr)
            {
                Console.WriteLine(item);
            }

 

Select的使用 將序列中的每個元素投影到新表單 投影

  int[] studentAges = { 18, 16, 17, 16, 22, 30, 19, 26, 33 };
            var list = studentAges.Where(c => c >= 18).Select(c => new { info = "成年的年齡有(>=18歲): " + c }).ToList();
            foreach (var obj in list)
                Console.WriteLine("{0}", obj.info);

 

SelectMany的使用 將序列的每個元素投影到一個 IEnumerable<T> 並將結果序列組合為一個 IQueryable<T> 型別的序列。

   List<StudentBookModel> models = new List<StudentBookModel>();
            models.Add(new StudentBookModel
            {
                sbid = "S001",
                sName = "魯智深",
                booksname = new List<Book> {
                    new Book { bid = "b001", bName = "西遊記" },new Book { bid = "b002", bName = "水滸傳" }, new Book { bid = "b003", bName = "三國演義" }
                }
            });
            models.Add(new StudentBookModel
            {
                sbid = "S002",
                sName = "武僧",
                booksname = new List<Book> {
                    new Book { bid = "b004", bName = "笑傲江湖" }, new Book { bid = "b005", bName = "楚留香" },new Book { bid = "b006", bName = "射鵰英雄傳" }
                }
            });
            //--兩層 for迴圈找出 bid=b002,和b006 的書本資訊
            {
                Console.WriteLine("==========foreach / for 多層迴圈=============="); //方法一:foreach / for 多層迴圈
                foreach (var item in models)
                {
                    foreach (var book in item.booksname)
                    {
                        if ("b002".Equals(book.bid) || "和b006".Equals(book.bid))
                        {
                            Console.WriteLine("foreach / for 多層迴圈 找到書的資訊: bid:{0}, bName:{1}", book.bid, book.bName);
                        }
                    }
                }
            }
            Console.WriteLine("=========from S in models linq to Sql寫法==============="); //方法二: 像是些SQL那樣,很是方便,層次也比較清晰
            {
                var booklist = (from S in models
                                from B in S.booksname
                                where new string[] { "b002", "b006" }.Contains(B.bid)
                                select new Book { bid = B.bid, bName = B.bName }).ToList();
                for (int i = 0; i < booklist.Count; i++)
                {
                    Console.WriteLine("from S in models 找到書的資訊bid:{0}, bName:{1} ", booklist[i].bid, booklist[i].bName);
                }
            }
            {
                Console.WriteLine("=========SelectMany==============="); //方法三:SelectMany
                var booklist = models.SelectMany(s => s.booksname).Where(c =>
                new string[] { "b002", "b006" }.Contains(c.bid)).Select(c => new Book
                {
                    bid = c.bid,
                    bName = c.bName
                }).ToList();
                Console.WriteLine("SelectMany 找到書的資訊: ", string.Join(" ", booklist));
            }

 

SequenceEqual的使用 確定兩個序列是否相等。

 Pet p1 = new Pet { Name = "Dog", Age = 2 };
                Pet p2 = new Pet { Name = "Pig", Age = 1 };
                Pet p3 = new Pet { Name = "Cat", Age = 3 };

                List<Pet> list01 = new List<Pet> { p1, p2, p3 };
                List<Pet> list02 = new List<Pet> { p1, p2, p3 };
                List<Pet> list03 = new List<Pet> { p2, p3, p1, };
                List<Pet> list04 = new List<Pet> { p1, p3 };

                bool flag01 = list01.SequenceEqual(list02);
                bool flag02 = list01.SequenceEqual(list03);
                bool flag03 = list01.SequenceEqual(list04);
                bool flag04 = list02.SequenceEqual(list03);
                Console.WriteLine($"list01.SequenceEqual(list02) => {flag01}");
                Console.WriteLine($"list01.SequenceEqual(list03) => {flag02}");
                Console.WriteLine($"list01.SequenceEqual(list04) => {flag03}");
                Console.WriteLine($"list02.SequenceEqual(list03) => {flag04}");

 

Single   SingleOrDefault的使用 下面是官方的解釋,由於比較簡單,這裡不再舉例說明

/*
             *  SingleOrDefault<TSource>(IQueryable<TSource>)
             返回序列中的唯一元素;如果該序列為空,則返回預設值;如果該序列包含多個元素,此方法將引發異常
             */

            /*
             *  SingleOrDefault<TSource>(IQueryable<TSource>, Expression<Func<TSource, Boolean>>)
             返回序列中滿足指定條件的唯一元素;如果這類元素不存在,則返回預設值;如果有多個元素滿足該條件,此方法將引發異常
             */

Skip Take的使用 一起使用,分頁的效果 Skip:跳過多少資料,Take拿取多少資料

 List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
                var newlist01 = list.Skip(2).ToList();
                var newlist02 = list.Skip(2).Take(3).ToList();
                Console.WriteLine("原來的資料集合" + string.Join(" ", list));
                Console.WriteLine("list.Skip(2)=> " + string.Join(" ", newlist01));
                Console.WriteLine("list.Skip(2).Take(3)=> " + string.Join(" ", newlist02));

 

ThenBy ThenByDescending的使用 排序時繼續按照其他的欄位來排序

   List<Pig> list = new List<Pig>
                {
                          new Pig{pid="p001",name="小豬",age=1 },
                          new Pig{pid="p004",name="八戒",age=500 },
                          new Pig{pid="p002",name="小八戒",age=100 },
                          new Pig{pid="p008",name="老年八戒",age=600 },
                          new Pig{pid="p003",name="青年豬",age=2 },
                          new Pig{pid="p003",name="老豬",age=10 },
                          new Pig{pid="p004",name="假八戒",age=-1 },
                          new Pig{pid="p008",name="成仙八戒",age=1000 }
                 };
                var newlist01 = list.OrderBy(c => c.pid).ToList();
                var newlist02 = list.OrderBy(c => c.pid).ThenBy(c => c.age).ToList();
                var newlist03 = list.OrderBy(c => c.pid).ThenByDescending(c => c.age).ToList();
                Console.WriteLine("===========newlist01=====按照pid從小到大排序==========");
                Console.WriteLine("pid asc排序:" + string.Join(" ", newlist01.Select(c => c.pid)));
                Console.WriteLine("age asc排序:" + string.Join(" ", newlist01.Select(c => c.age)));
                Console.WriteLine();
                Console.WriteLine("===========newlist02====按照pid從小到大並且年齡從小到大排序===========");
                Console.WriteLine("pid asc排序:" + string.Join(" ", newlist02.Select(c => c.pid)));
                Console.WriteLine("age asc排序:" + string.Join(" ", newlist02.Select(c => c.age)));
                Console.WriteLine();
                Console.WriteLine("===========newlist03===按照pid從小到大並且年齡從大到小排序============");
                Console.WriteLine("pid asc排序:" + string.Join(" ", newlist03.Select(c => c.pid)));
                Console.WriteLine("age asc排序:" + string.Join(" ", newlist03.Select(c => c.age)));

Union 的使用 生成兩個序列的並集。 類似 sql中的Unio 會去重

 int[] list01 = { 5, 6, 9, 8, 3, 1, 7 };
                int[] list02 = { 3, 6, 4, 8, 2, 5, 1, 9 };
                List<Pet> listpet01 = new List<Pet> {
                    new Pet{ Name="Dog1",Age=2},
                    new Pet{ Name="Dog2",Age=1}
                };
                List<Pet> listpet02 = new List<Pet> {
                    new Pet{ Name="cat",Age=3},
                    new Pet{ Name="pig",Age=1},
                    new Pet{ Name="bird",Age=5}
                };
                var newlist = list01.(list02);
                var newlist2 = listpet01.Union(listpet02).Select(c => c.Name).ToList();

                Console.WriteLine("陣列結合unio之後:" + string.Join(" ", newlist));
                Console.WriteLine("我有如下這些寵物:" + string.Join("; ", newlist2));

 

ToDictionary 的使用 下面為官方的擴充套件方法字串

 /*
             public static System.Collections.Generic.Dictionary<TKey,TSource> ToDictionary<TSource,TKey> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,TKey> keySelector);
             */
            List<Person> ps = new List<Person> {
                     new Person{ Name="小張",Age=22,Country="中國",Sex=""},
                     new Person{ Name="小鄭",Age=21,Country="中國",Sex=""},
                     new Person{ Name="Zhang",Age=32,Country="English",Sex=""},
                     new Person{ Name="Jason",Age=29,Country="English",Sex=""},
                     new Person{ Name="Luce",Age=21,Country="USA",Sex=""},
                     new Person{ Name="Peter",Age=22,Country="English",Sex=""},
                     new Person{ Name="Tom",Age=32,Country="English",Sex=""},
                     new Person{ Name="小紅",Age=28,Country="中國",Sex=""},
                     new Person{ Name="小鐘",Age=31,Country="中國",Sex=""}
               };
            Dictionary<string, int> dic1 = ps.ToDictionary(p => p.Name, a => a.Age);
            Dictionary<string, Person> dic2 = ps.ToDictionary(p => p.Name);


            foreach (KeyValuePair<string, int> item in dic1)
            {
                Console.WriteLine("key:{0},age:{1}", item.Key, item.Value);
            }
            Console.WriteLine("===============value為物件型別的資料================");
            foreach (KeyValuePair<string, Person> item in dic2)
            {
                Console.WriteLine("key:{0},age:{1},Country:{2},sex:{3}", item.Key, item.Value.Age, item.Value.Country, item.Value.Sex);
            }

 

Sum,Min,Max,Average等的使用 這些還是比較簡單,還是簡單舉例一下吧,看到的寶寶們是否會點個贊啊?嘻嘻

            List<decimal> listdecime = new List<decimal> { 58m, 66, 90m, 60, 88m, 70m, 99m, 76m, 83m };
            decimal maxScore = listdecime.Max();
            decimal minScore = listdecime.Min();
            decimal sumScore = listdecime.Sum();
            decimal avgScore = listdecime.Average();
            decimal avgScoreFromart = Math.Round(avgScore, 2);
            Console.WriteLine("最大分數{0},最小分數{1},總分數{2},平均分數{3},保留數字後兩位小數點{4}", maxScore, minScore, sumScore, avgScore, avgScoreFromart);

 

ToLookup的使用 從 IEnumerable<T> 生成一個泛型 Lookup<TKey,TElement>,寶寶表示沒有看懂?啥東東? 我這裡就給寶寶們列舉一個案例demo

  List<Pig> stulist = new List<Pig> {
                new Pig{pid="P001",name="小豬1",age=1 },
                new Pig{pid="P002",name="小豬2",age=2 },
                new Pig{pid="P001",name="小豬1",age=1 },
                new Pig{pid="P002",name="小豬2",age=2 },
                new Pig{pid="P001",name="小豬1",age=1 },
                new Pig{pid="P003",name="小豬3",age=3 },
                new Pig{pid="P003",name="小豬3",age=3 },
                new Pig{pid="P001",name="小豬1",age=1 },
                new Pig{pid="P004",name="小豬4",age=4 },
                new Pig{pid="P003",name="小豬3",age=3 }
            };
            // 這裡就不在輸出GroupBy了,stulist.GroupBy(p => p.pid).ToList();
            List<IGrouping<string, Pig>> Luplist = stulist.ToLookup(p => p.pid).ToList();
            var newlist = stulist.ToLookup(c => c.pid, p => new { p.pid, p.name, p.age }).ToList();

            foreach (var item in Luplist)
            {
                Console.WriteLine("========key:{0}==========", item.Key);
                foreach (var info in item)
                {
                    Console.WriteLine("pid:{0}, name:{1}, age:{2}", info.pid, info.name, info.age);
                }
            }

  

Zip的使用 類似拉鍊的效果 將指定函式應用於兩個序列的對應元素,以生成結果序列,啥東東??

第一眼還以為是壓縮的啥東東, 後來仔細看文件才清白,完全就不是一回事,嘻嘻!
            string[] listPerson = { "孫悟空", "豬八戒", "沙悟淨", "唐三藏", "白骨精", "如來佛" };
            int[] ages = { 600, 500, 400, 1000, 300, 1100 };
            IEnumerable<(string, int)> listobj = listPerson.Zip(ages);//這裡故意寫出前面的型別是為了方便了返回的型別是啥
            foreach (var item in listobj)
                Console.WriteLine("姓名:{0}, 年齡:{1}", item.Item1, item.Item2);

6:一些使用的臨時model

別再眼高手低了! 這些Linq方法都清楚地掌握了嗎?
 class Pet
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
        class Student
        {
            public string sid { get; set; }
            public string sName { get; set; }
            public string bookid { get; set; }
        }

        class StudentBookModel
        {

            public string sbid { get; set; }
            public string sName { get; set; }
            public List<Book> booksname { get; set; }
        }
        class Book
        {
            public string bid { get; set; }
            public string bName { get; set; }
        }

        class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public string Country { get; set; }
            public string Sex { get; set; }
        }

        class MyDog<T> : List<T>
        {
            public IEnumerable<T> MyWhere(Func<T, bool> func)
            {
                return Enumerable.Where(this, func);
            }
        }

        class Pig
        {
            public string pid { get; set; }
            public string name { get; set; }
            public int age { get; set; }
        }
View Code

 7:好了,先到這裡,歡迎大家留言,指教,謝謝

 

相關文章