日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Linq 学习笔记(二)

發(fā)布時(shí)間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linq 学习笔记(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Linq 學(xué)習(xí)筆記(二)

下面就來(lái)介紹一些查詢的示例:

1。Linq查詢

var racers = from r in Formula1.GetChampions()
where r.Wins > 15 && (r.Country == "Brazil" || r.Country == "Austria") select r;
foreach (var r in racers)
{
Responose.Write("{0:A}", r);
}

使用擴(kuò)展方法的查詢

并不是所有的查詢都可以用LINQ查詢完成。也不是所有的擴(kuò)展方法都映射到LINQ查詢子句上。高級(jí)查詢需要使用擴(kuò)展方法。為了更好地理解帶擴(kuò)展方法的復(fù)雜查詢,最好看看簡(jiǎn)單的查詢是如何映射的。使用擴(kuò)展方法Where()和Select(),會(huì)生成與前面LINQ 查詢非常類似的結(jié)果:

var racers = Formula1.GetChampions().Where(r => r.Wins > 15 && (r.Country == "Brazil" || r.Country == "Austria")).Select(r = > r);

2。用索引來(lái)過(guò)濾

不能使用LINQ 查詢的一個(gè)例子是Where()方法的重載。在Where()方法的重載中,可以傳送第二個(gè)參數(shù)——索引。索引是過(guò)濾器返回的每個(gè)結(jié)果的計(jì)數(shù)器。可以在表達(dá)式中使用這個(gè)索引,執(zhí)行基于索引的計(jì)算。下面的代碼由Where()擴(kuò)展方法調(diào)用,它使用索引返回姓氏以A開(kāi)頭、索引為偶數(shù)的賽手:

var racers = Formula1.GetChampions().Where((r, index) => r.LastName.StartsWith("A") &&

index % 2 != 0);
foreach (var r in racers)
{
Responose.Write("{0:A}", r);

}

3。類型過(guò)濾

為了進(jìn)行基于類型的過(guò)濾,可以使用OfType()擴(kuò)展方法。這里數(shù)組數(shù)據(jù)包含string和int對(duì)象。使用OfType()擴(kuò)展方法,把string類傳送給泛型參數(shù),就從集合中返回字符串。

object[] data = { "one", 2, 3, "four", "five",6 };
var query = data.OfType<string>();
foreach (var s in query)
{
Console.WriteLine(s);
}

4。復(fù)合的from子句

var ferrariDrivers = from r in Formula1.GetChampions() from c in r.Cars where c == "Ferrari"
orderby r.LastName select r.FirstName + " " + r.LastName;?

C#編譯器把復(fù)合的from 子句和LINQ 查詢轉(zhuǎn)換為SelectMany()擴(kuò)展方法。SelectMany()可用于迭代序列的序列。示例中SelectMany()方法的重載版本如下所示:

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

第一個(gè)參數(shù)是隱式參數(shù),從GetChampions()方法中接收Racer對(duì)象序列。第二個(gè)參數(shù)是collectionSelector委托,它定義了內(nèi)部序列。在λ表達(dá)式r=>r.Cars中,應(yīng)返回賽車集合。第三個(gè)參數(shù)是一個(gè)委托,現(xiàn)在為每個(gè)賽車調(diào)用該委托,接收Racer和Car對(duì)象。λ表達(dá)式創(chuàng)建了一個(gè)匿名類型,它帶Racer和Car屬性。這個(gè)SelectMany()方法的結(jié)果是攤平了賽手和賽車的層次結(jié)構(gòu),為每輛賽車返回匿名類型的一個(gè)新對(duì)象集合。

這個(gè)新集合傳送給Where()方法,過(guò)濾出駕駛Ferrari 的賽手。最后,調(diào)用OrderBy()和Select()方法:
var ferrariDrivers = Formula1.GetChampions().SelectMany(r => r.Cars,
(r, c) => new { Racer = r, Car = c }).Where(r => r.Car == "Ferrari").OrderBy(r =>r.Racer.LastName).Select(r => r.Racer.FirstName + " " +r.Racer.LastName);
把SelectMany()泛型方法解析為這里使用的類型,所解析的類型如下所示。在這個(gè)例子中,數(shù)據(jù)源是
Racer類型,所過(guò)濾的集合是一個(gè)string數(shù)組,當(dāng)然所返回的匿名類型的名稱是未知的,這里顯示為TResult:
public static IEnumerable<TResult> SelectMany<Racer, string, TResult>(
this IEnumerable<Racer> source,Func<Racer,IEnumerable<string>> collectionSelector,
Func<Racer,string,TResult> resultSelector);
查詢僅從LINQ 查詢轉(zhuǎn)換為擴(kuò)展方法,所以結(jié)果與前面的相同。

5。排序

var racers = from r in Formula1.GetChampions() where r.Country == "Brazil" orderby r.Wins descending select r;

orderby子句解析為OrderBy()方法,orderby descending子句解析為OrderBy Descending()方法:

var racers = Formula1.GetChampions().Where(r => r.Country == "Brazil").OrderByDescending(r => r.Wins).Select(r => r);

OrderBy()和OrderByDescending()方法返回IOrderEnumerable<TSource>。這個(gè)接口派生于接口IEnumerable<TSource>,但包含一個(gè)額外的方法CreateOrderedEnumerable-<TSource>()。這個(gè)方法用于進(jìn)一步給序列排序。如果根據(jù)關(guān)鍵字選擇器來(lái)排序,兩項(xiàng)的順序相同,就可以使用ThenBy()和ThenByDescending()方法繼續(xù)排序。這兩個(gè)方法需要IOrderEnumerable<TSource>才能工作,但也返回這個(gè)接口。所以,可以添加任意多個(gè)ThenBy()和ThenByDescending()方法,對(duì)集合排序。

使用LINQ 查詢時(shí),只需把所有用于排序的不同關(guān)鍵字(用逗號(hào)分隔開(kāi))添加到orderby 子句中例如

var racers = (from r in Formula1.GetChampions() orderby r.Country, r.LastName, r.FirstName select r).Take(10);

6。分組

var countries = from r in Formula1.GetChampions() group r by r.Country into g orderby g.Count() descending, g.Key where g.Count() >= 2 select new { Country = g.Key, Count = g.Count() };
foreach (var item in countries)
{
Response.Write("{0, -10} {1}",item.Country, item.Count);
}

擴(kuò)展方法的分組表示:

var countries = Formula1.GetChampions().GroupBy(r => r.Country).OrderByDescending(g => g.Count()).
ThenBy(g => g.Key).Where(g => g.Count() >= 2).Select(g => new { Country = g.Key,Count = g.Count()});

7。對(duì)嵌套的對(duì)象分組

如果分組的對(duì)象應(yīng)包含嵌套的對(duì)象,就可以改變select 子句創(chuàng)建的匿名類型。

var countries = from r in Formula1.GetChampions() group r by r.Country into g orderby g.Count() descending, g.Key where g.Count() >= 2 select new
{
Country = g.Key, Count = g.Count(),

Racers = from r1 in g orderby r1.LastName select r1.FirstName + " " + r1.LastName
};
foreach (var item in countries)
{
Response.Write("{0, -10} {1}", item.Country, item.Count);
foreach (var name in item.Racers)
{
Response.Write("{0}; ", name);
}
Response.Write("<br/>");
}

8。連接

使用join 子句可以根據(jù)特定的條件合并兩個(gè)數(shù)據(jù)源,但之前要獲得兩個(gè)要連接的列表。

var racers = from r in Formula1.GetChampions() from y in r.Years where y > 2003 select new
{
Year = y,
Name = r.FirstName + " " + r.LastName
};

var teams = from t in Formula1.GetContructorChampions() from y in t.Years where y > 2003

select new { Year = y, Name = t.Name };

有了這兩個(gè)查詢,再通過(guò)子句join t in teams on r.Year equals t.Year就可以得到結(jié)果集了。

var racersAndTeams = from r in racers join t in teams on r.Year equals t.Year select new
{
Year = r.Year,
Racer = r.Name,
Team = t.Name
};
Response.Write("Year Champion " + "Constructor Title");
foreach (var item in racersAndTeams)
{
Response.Write("{0}: {1,-20} {2}",item.Year, item.Racer, item.Team);
}

9。設(shè)置操作

擴(kuò)展方法Distinct()、Union()、Intersect()和Except()都是設(shè)置操作。

var ferrariDrivers = from r in Formula1.GetChampions() from c in r.Cars where c == "Ferrari"
orderby r.LastName select r;
現(xiàn)在建立另一個(gè)相同的查詢,但where 子句的參數(shù)不同,以獲得所有駕駛McLaren 的冠軍。最好不要再次編寫相同的查詢。而可以創(chuàng)建一個(gè)方法,給它傳送參數(shù)car:
private static IEnumerable<Racer> GetRacersByCar(string car)
{
return from r in Formula1.GetChampions() from c in r.Cars where c == car orderby r.LastName select r;
}
但是,因?yàn)樵摲椒ú恍枰谄渌胤绞褂?#xff0c;所以應(yīng)定義一個(gè)委托類型的變量來(lái)保存LINQ 查詢。變量racerByCar 必須是一個(gè)委托類型,它需要一個(gè)字符串參數(shù),返回IEnumerable <Racer>,類似于前面實(shí)現(xiàn)的方法。為此,定義了幾個(gè)泛型委托Func<>,所以不需要聲明自己的委托。把一個(gè)λ表達(dá)式賦予變量racerByCar。λ表達(dá)式的左邊定義了一個(gè)car 變量,其類型是Func 委托的第一個(gè)泛型參數(shù)(字符串)。右邊定義了LINQ 查詢,它使用該參數(shù)和where 子句:
Func<string, IEnumerable<Racer>> racersByCar = Car => from r in Formula1.GetChampions() from c in r.Cars where c == car orderby r.LastName select r;
現(xiàn)在可以使用Intersect()擴(kuò)展方法,獲得駕駛Ferrari 和McLaren 的所有冠軍:
Response.Write("World champion with " + "Ferrari and McLaren");
foreach (var racer in racersByCar("Ferrari").
Intersect(racersByCar("McLaren")))
{
Response.Write(racer);
}

10。分區(qū)

擴(kuò)展方法Take()和Skip()等的分區(qū)操作可用于分頁(yè),例如顯示5×5 個(gè)賽手。在下面的LINQ 查詢中,擴(kuò)展方法Take()和Skip()添加到查詢的最后。Skip()方法先忽略根據(jù)頁(yè)面的大小和實(shí)際的頁(yè)數(shù)計(jì)算出的項(xiàng)數(shù),再使用方法Take()根據(jù)頁(yè)面的大小提取一定數(shù)量的項(xiàng):
int pageSize = 5;
int numberPages = (int)Math.Ceiling(Formula1.GetChampions().Count()/(double)pageSize);

for (int page = 0; page < numberPages; page++)
{
Response.Write("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)
{
Response.Write(name);
}
Response.Write();
}

11。合計(jì)操作符

合計(jì)操作符如Count()、Sum()、Min()、Max()、Average()和Aggregate(),不返回一個(gè)序列,而返
回一個(gè)值。

var query = from r in Formula1.GetChampions() where r.Years.Count() > 3 orderby r.Years.Count() descending select new
{
Name = r.FirstName + " " +r.LastName,
TimesChampion = r.Years.Count()
};
foreach (var r in query)
{
Response.Write("{0} {1}", r.Name, r.TimesChampion);
}

Sum()方法匯總序列中的所有數(shù)字,返回這些數(shù)字的和。下面的Sum()用于計(jì)算一個(gè)國(guó)家贏得比賽的
總次數(shù)。首先根據(jù)國(guó)家對(duì)賽手分組,再在新創(chuàng)建的匿名類型中,給Wins 屬性賦予某個(gè)國(guó)家贏得比賽的總
次數(shù)。

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)
{
Response.Write("{0} {1}",country.Country, country.Wins);
}

方法Min()、Max()、Average()和Aggregate()的使用方式與Count()和Sum()相同。Min()返回集合
中的最小值,Max()返回集合中的最大值,Average()計(jì)算集合中的平均值。對(duì)于Aggregate()方法,可
以傳送一個(gè)λ表達(dá)式,對(duì)所有的值進(jìn)行匯總。

12。轉(zhuǎn)換

查詢可以推遲到訪問(wèn)數(shù)據(jù)項(xiàng)時(shí)再執(zhí)行。在迭代中使用查詢,查詢會(huì)執(zhí)行。而使用轉(zhuǎn)換操作符會(huì)立即執(zhí)行查詢,把結(jié)果放在數(shù)組、列表或字典中。在下面的例子中,調(diào)用ToList()擴(kuò)展方法,立即執(zhí)行查詢,把結(jié)果放在List<T>中:

List < Racer > racers = (from r in Formula1.GetChampions()
where r.Starts > 150 orderby r.Starts descending select r).ToList();
foreach (var racer in racers)
{
Response.Write("{0} {0:S}", racer);
}

把返回的對(duì)象放在列表中并沒(méi)有這么簡(jiǎn)單。例如,對(duì)于集合中從賽車到賽手的快速訪問(wèn),可以使用新類Lookup<TKey, TElement>。

提示:
Dictionary<TKey, TValue>只支持一個(gè)鍵對(duì)應(yīng)一個(gè)值。在System.Linq 命名空間的類Lookup<TKey,
TElement>中,一個(gè)鍵可以對(duì)應(yīng)多個(gè)值。這些類詳見(jiàn)第10 章。
使用復(fù)合的from 查詢,可以攤平賽手和賽車序列,創(chuàng)建帶有Car 和Racer 屬性的匿名類型。在返回的Lookup 對(duì)象中,鍵的類型應(yīng)是表示汽車的string,值的類型應(yīng)是Racer。為了進(jìn)行這個(gè)選擇,可以給ToLookup()方法的一個(gè)重載版本傳送一個(gè)鍵和一個(gè)元素選擇器。鍵選擇器表示Car 屬性,元素選擇器表示Racer 屬性。

ILookup<string, Racer> racers = (from r in Formula1.GetChampions() from c in r.Cars select new
{ Car = c, Racer = r }).ToLookup(cr = > cr.Car, cr = > cr.Racer);
if (racers.Contains("Williams"))
{
foreach (var williamsRacer in racers["Williams"])
{
Response.Write(williamsRacer);
}
}

如果需要在未類型化的集合上使用LINQ查詢,例如ArrayList,就可以使用Cast()方法。在下面的例子中,基于Object 類型的ArrayList 集合用Racer 對(duì)象填充。為了定義強(qiáng)類型化的查詢,可以使用Cast()方法。
System.Collections.ArrayList list = new System.Collections.ArrayList(Formula1.GetChampions() as
System.Collections.ICollection);
var query = from r in list.Cast <Racer>() where r.Country == "USA" orderby r.Wins descending select r;
foreach (var racer in query)
{
Response.Write("{0:A}", racer);
}

13。生成操作符

生成操作符Range()、Empty()和Repear()不是擴(kuò)展方法,而是返回序列的正常靜態(tài)方法。在LINQto Objects 中,這些方法可用于Enumerable 類。有時(shí)需要填充一個(gè)范圍的數(shù)字,此時(shí)就應(yīng)使用Range()方法。這個(gè)方法把第一個(gè)參數(shù)作為起始值,把第二個(gè)參數(shù)作為要填充的項(xiàng)數(shù)。
var values = Enumerable.Range(1, 20);
foreach (var item in values)
{
Response.Write("{0} ", item);
}
Range()方法不返回填充了所定義值的集合,這個(gè)方法與其他方法一樣,也推遲執(zhí)行查詢,返回一個(gè)RangeEnumerator,其中只有一個(gè)yield return 語(yǔ)句,來(lái)遞增值。可以把該結(jié)果與其他擴(kuò)展方法合并起來(lái),獲得另一個(gè)結(jié)果,例如使用Select()擴(kuò)展方法:
var values = Enumerable.Range(1, 20).Select(n = > n * 3);
Empty()方法返回一個(gè)不返回值的迭代器,它可以用于參數(shù)需要一個(gè)集合,且可以給參數(shù)傳送空集
合的情形。Repeat()方法返回一個(gè)迭代器,該迭代器把同一個(gè)值重復(fù)特定的次數(shù)。

?

?

ASP.NET開(kāi)發(fā)技術(shù)交流群: 67511751(人員招募中...)

posted on 2011-08-31 16:03 Juvy 閱讀(...) 評(píng)論(...) 編輯 收藏

轉(zhuǎn)載于:https://www.cnblogs.com/Juvy/archive/2011/08/31/2160847.html

總結(jié)

以上是生活随笔為你收集整理的Linq 学习笔记(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。