不要再眼高手低了,这些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

 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; }
}

7:好了,先到这里,欢迎大家留言,指教,谢谢!

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?的更多相关文章

  1. 实战c++中的vector系列--再谈vector的insert()方法(都是make_move_iterator惹的祸)

    之前说过了关于vector的insert()方法,把vector B的元素插入到vector A中.vector A中的结果我们可想而知,可是vector B中的元素还会怎样? 看看之前写过的程序: ...

  2. LINQ之路 4:LINQ方法语法

    书写LINQ查询时又两种语法可供选择:方法语法(Fluent Syntax)和查询语法(Query Expression). LINQ方法语法是非常灵活和重要的,我们在这里将描述使用链接查询运算符的方 ...

  3. hive权威安装出现的不解错误!(完美解决)两种方法都可以

    以下两种方法都可以,推荐用方法一! 方法一: 步骤一: yum -y install mysql-server 步骤二:service mysqld start 步骤三:mysql -u root - ...

  4. 四:MVC之LINQ方法语法

    linq 查询 有两种语法  ,前面我们说了一种,接下来说方法语法(我读着一直很绕口) 查询语法,方法语法 ------------------------以下文字都是复制-------------- ...

  5. 别再写getter,setter方法了,用Lombok来简化你的代码吧

    前言 在实际开发中,有些代码是重复的.IDE一键生成的,不写不行,写了又觉得代码太臃肿,不美观.如果你也有这种体会,那么,请使用Lombok插件吧,真的非常好用.Lombok的使用也非常简单,都是各种 ...

  6. AppStore下载失败使用已购页面再试一次解决方法

    AppStore载失败 使用已购页面再试一次解决方法 工具/原料 Mac OS 方法/步骤 1.大家可以先试试更改系统 DNS 的方法,由于苹果的 App Store 应用商店在国外,所以 DNS 如 ...

  7. ASP.NET弹出提示点击确定之后再跳转页面的方法

    //ASP.NET弹出提示点击确定之后再跳转页面的方法 //弹出了提示并且通过location.href转到了DeskTop.aspx页面 Response.Write("<scrip ...

  8. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

  9. JS函数可以再添加属性(包括方法)

    1 前言 JS函数可以再添加属性(包括方法),这个有点有趣,记录一下. 2 代码 <!DOCTYPE html> <html> <head> <title&g ...

随机推荐

  1. C#设计模式之3-建造者模式

    建造者模式(Builder Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/393 访问. 建造者模式属 ...

  2. Android 禁止ViewPager左右滑动的功能实现

    来来来,各位看官~ Look here!!! Android    禁止ViewPager左右滑动的功能实现!! I think it`s so easy,无需重写ViewPager!!! JUST ...

  3. java泛型笔记

    目录 概述 什么是泛型?为什么使用泛型? 例子 特性 使用方式 泛型类 泛型接口 泛型通配符 泛型方法 泛型方法的基本用法 类中的泛型方法 泛型方法的基本用法 泛型方法与可变参数 静态方法与泛型 泛型 ...

  4. ajax、反向ajax、jsonp详解

    ajax详解 什么是ajax 其实ajax已经属于老技术了,现在几乎没人不会用了,在这里主要是把底层的东西给大家分享一下,以备应对装逼的面试官. ajax即“Asynchronous Javascri ...

  5. maven命令下载jar包

    mvn install:install-file -Dfile=jar包保存的本地路径 -DgroupId=jar保存的父级路径 -DartifactId=jar包文件夹名称 -Dversion=版本 ...

  6. linux 基本命令整理--转

      推荐:http://www.cnblogs.com/lingiu/p/3446647.html 1. 查看目录文件:ls2. 查看目前路径:psw3. 查看文件内容:cat 文件名4. 打开编辑器 ...

  7. 计算机网络-应用层(5)P2P应用

    P2P系统的索引:信息到节点位置(IP地址+端口号)的映射 在文件共享(如电驴中):利用索引动态跟踪节点所共享的文件的位置.节点需要告诉索引它拥有哪些文件.节点搜索索引从而获知能够得到哪些文件 在即时 ...

  8. 算法-搜索(6)B树

    B树是平衡的m路搜索树. 根结点至少两个子女,根结点以外的非失败结点至少⌈m/2⌉个子女,所有失败结点都在h+1层. 第h层至少2⌈m/2⌉h-1个结点,因此失败结点数n+1≥2⌈m/2⌉h-1个. ...

  9. 区块链入门到实战(23)之以太坊(Ethereum) – 虚拟机架构

    以太坊(Ethereum)网络中,定义了一组通用协议用于支持智能合约的运行,其核心便是以太坊(Ethereum)虚拟机. 下图解释了该架构: 开发人员使用Solidity等开发语言开发智能合约 源程序 ...

  10. 轻轻松松学CSS:background

    background是复合属性,它可以分解为8个属性,其中5个属于CSS,另外3个属于CSS3一.CSS    1.background-color:背景色    2.background-image ...