c#-LINQ与lambda表达式学习笔记
https://blog.csdn.net/m0_56259289/article/details/144134122
static void Main(string[] args) //程序入口
{
int[] arr1 = new int[] { 1, 2, 3, 4, 5, 6, 7 };
int[] arr2 = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var query1 = from n in arr1 select n;
var query2 = from a in arr1
from b in arr2
select a + b;
var query3 = from n in arr2 select n * 10;
var query4 = from n in arr2
select new
{
Id = n,
name = n.ToString()
};
var query11 = from n in arr1
where n < 3
select n;
}
class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Class { get; set; }
}
List<Student> students = new List<Student>
{
new Student { Name = "Alice", Age = 20, Class = "A" },
new Student { Name = "Bob", Age = 22, Class = "B" },
new Student { Name = "Charlie", Age = 21, Class = "A" },
new Student { Name = "David", Age = 23, Class = "B" },
new Student { Name = "Eve", Age = 20, Class = "C" }
};
var studentGroups = from s in students
group s by s.Class into g
select new { Class = g.Key, Count = g.Count() };
foreach (var group in studentGroups)
{
Console.WriteLine($"Class: {group.Class}, Number of Students: {group.Count}");
}
方法调用where
public static bool IsEven(int n)
{
return n % 2 == 0 ? true : false;
}
static void Main(string[] args) //程序入口
{
int[] arr = new int[] {1,2,3,4,5,6,7,8 };
var query = from n in arr
where IsEven(n)
select n;
foreach (var n in query)
{
Console.WriteLine(n);
}
}
let
int[] arr = new int[] {1,2,3,4,5,6,7,8 };
var query = from num in arr
let n = num % 2
where n==0
select num;
foreach (var n in query)
{
Console.WriteLine(n);
}
orderby
var query = from n in arr
where n > 1 && n < 6
orderby n descending
select n;
group by
int[] arr = new int[] {1,2,3,4,5,6,7,8 };
var query = from n in arr
where n > 1 && n < 6
group n by n % 2;
foreach (var n in query)
{
foreach (var j in n)
{
Console.WriteLine(j);
}
}
int[] arr = new int[] {1,2,3,4,5,6,7,8 };
var query = from n in arr
where n > 1 && n < 6
group n by n % 2 into g
from sn in g
select sn;
foreach (var n in query)
{
Console.WriteLine(n);
}
join
nt[] arr1 = new int[] {1,2,3,4,5,6,7,8 };
int[] arr2 = new int[] { 1,4, 5, 6,8 };
var query = from a in arr1
where a < 7
join b in arr2 on a equals b
select a;
//将arr1和arr2数组连接,同时满足a,b相等的条件,其中b是arr2中的元素
LINQ构架
IEnumerable var 二者相等
IEnumerable<int> scoreQuery =
from score in arr1
where score > 2
select score;
var scoreQuery2 = from score in arr1
where score > 2
select score;
key
string[] langusges = { "java", "c#", "c++", "python", "vb" };
var query = from item in langusges
group item by item.Length into lengthgroups
orderby lengthgroups.Key
select lengthgroups;
foreach (var n in query)
{
Console.WriteLine(n.Key);
}
武学案例
var master = new List<MartialArtsMaster>()
{
new MartialArtsMaster() { Id = 1, Name = "黄蓉", Age = 18, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 9 },
new MartialArtsMaster() { Id = 7, Name = "黄蓉2", Age = 18, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 93 },
new MartialArtsMaster() { Id = 2, Name = "洪七公", Age = 34, Menpai = "丐帮", Kungfu = "没有", Level = 4 },
new MartialArtsMaster() { Id = 3, Name = "郭靖", Age = 54, Menpai = "黑帮", Kungfu = "细心打法", Level = 10 },
new MartialArtsMaster() { Id = 4, Name = "任我行", Age = 76, Menpai = "明教", Kungfu = "葵花宝典", Level = 14 },
new MartialArtsMaster() { Id = 5, Name = "东方不败", Age = 95, Menpai = "华山", Kungfu = "葵花宝典", Level = 20 },
new MartialArtsMaster() { Id = 6, Name = "岳不群", Age = 26, Menpai = "华山", Kungfu = "葵花宝典", Level = 20 }
};
var kongfu = new List<kungfu>()
{
new kungfu() { kuongfuId = 1, kongfuName = "打狗棒法", Lethality = 90 },
new kungfu() { kuongfuId = 2, kongfuName = "没有", Lethality = 95 },
new kungfu() { kuongfuId = 3, kongfuName = "细心打法", Lethality = 50 },
new kungfu() { kuongfuId = 4, kongfuName = "葵花宝典", Lethality = 99 }
};
var GaiBangMaster = from m in master
where m.Level > 8 && m.Menpai == "丐帮"
select m;
var GaiBangMethod = master.Where(m => m.Level > 8 && m.Menpai == "丐帮");
string matserLevel = "查询丐帮中武力值大于8:";
foreach(var num in GaiBangMaster)
{
matserLevel = num.Id + " "+num.Name + " "+ num.Age + " " +num.Menpai +" "+ num.Kungfu +" "+ num.Level +"\n" ;
Console.WriteLine(matserLevel);
}
foreach (var num in GaiBangMethod)
{
matserLevel = num.Id + " " + num.Name + " " + num.Age + " " + num.Menpai + " " + num.Kungfu + " " + num.Level + "\n";
Console.WriteLine(matserLevel);
}
var masterkongfumethod = master.SelectMany(k => kongfu, (m, k) => new { mt = m, kf = k })
.Where(x => x.kf.Lethality > 90 && x.mt.Kungfu == x.kf.kongfuName)
.OrderBy(m => m.mt.Level)
.Select(m => m.mt + " " + m.mt.Name + " " + m.mt.Age + " " + m.mt.Menpai + "\n");
var topmaster = from m in master
from k in kongfu
where k.kongfuName == m.kungfu
orderby m.leverl * k.lethality + m.age
select m.id + " " + m.Name + " " + m.age + " " + m.kunggu + " " + m.level;
var topmaster = master
.Join(kongfu, m => m.kungfu, k => k.kongfuName, (m, k) => new { m, k })
.OrderBy(x => x.m.leverl * x.k.lethality + x.m.age)
.Select(x => $"{x.m.id} {x.m.Name} {x.m.age} {x.m.kunggu} {x.m.level}");
.Select(x => new { id = x.Id, Name = x.Name, masterJongfu = x.Kungfu, Leverl = x.Level, Top = (++i) });这里的意思是并不想直接返回master对象,而是创建一个匿名对象,返回master的部分属性,和自己添加的属性
int i = 1;
var masterTop = master.Where(x => x.Level > 8)
.OrderByDescending(x => x.Level)
.Select(x => new { id = x.Id, Name = x.Name, masterJongfu = x.Kungfu, Leverl = x.Level, Top = (++i) });
案例
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace studytest //命名空间
{
class Program //类
{
static void Main(string[] args) //程序入口
{
var master = new List<MartialArtsMaster>()
{
new MartialArtsMaster() { Id = 1, Name = "黄蓉", Age = 18, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 9 },
new MartialArtsMaster() { Id = 7, Name = "黄蓉2", Age = 18, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 93 },
new MartialArtsMaster() { Id = 2, Name = "洪七公", Age = 34, Menpai = "丐帮", Kungfu = "没有", Level = 4 },
new MartialArtsMaster() { Id = 3, Name = "郭靖", Age = 54, Menpai = "黑帮", Kungfu = "细心打法", Level = 10 },
new MartialArtsMaster() { Id = 4, Name = "任我行", Age = 76, Menpai = "明教", Kungfu = "葵花宝典", Level = 14 },
new MartialArtsMaster() { Id = 5, Name = "东方不败", Age = 95, Menpai = "华山", Kungfu = "葵花宝典", Level = 20 },
new MartialArtsMaster() { Id = 6, Name = "岳不群", Age = 26, Menpai = "华山", Kungfu = "葵花宝典", Level = 20 }
};
var kongfu = new List<kungfu>()
{
new kungfu() { kuongfuId = 1, kongfuName = "打狗棒法", Lethality = 90 },
new kungfu() { kuongfuId = 2, kongfuName = "没有", Lethality = 95 },
new kungfu() { kuongfuId = 3, kongfuName = "细心打法", Lethality = 50 },
new kungfu() { kuongfuId = 4, kongfuName = "葵花宝典", Lethality = 99 },
new kungfu() { kuongfuId = 5, kongfuName = "九阳真经", Lethality = 95 }
};
//test1
var menpaiNum = master.Where(x => x.Menpai == "丐帮")
.OrderByDescending(x => x.Level)
.Select(x => new { Name = x.Name, Menpai = x.Menpai, kungfu = x.Kungfu, Level = x.Level, gg = "111" });
foreach (var m in menpaiNum)
{
Console.WriteLine(m.Name + " " + m.Menpai + " " + m.kungfu + " " + m.Level + " " + m.gg);
}
//test2
var eqkungfuNum = master.Join(kongfu, m => m.Kungfu, k => k.kongfuName, (m, k) =>
new { m.Name, m.Kungfu, k.kongfuName,k.Lethality });
foreach(var m in eqkungfuNum)
{
Console.WriteLine($"master: {m.Name},kungfu:{m.Kungfu}m.Lethality");
}
//lambda表达式
int i = 1;
var masterTop = master.Where(x => x.Level > 8)
.OrderByDescending(x => x.Level)
.Select(x => new { id = x.Id, Name = x.Name, masterKongfu = x.Kungfu, Leverl = x.Level, Top = (++i) });
//LINQ经典
int ii = 1;
var KongfuTop = from k in kongfu
where k.Lethality > 90
orderby k.Lethality descending
select new { KongfuId = k.kuongfuId, kongfuName = k.kongfuName, Lethality = k.Lethality, KongfuTop = (ii++) };
//
var masterLethalityTop = from m in masterTop
join k in KongfuTop on m.masterKongfu equals k.kongfuName
orderby m.Leverl * k.Lethality descending
select new { Id = m.id, Name = m.Name, kongfu = m.masterKongfu, Lever = m.Leverl, Kill = m.Leverl * k.Lethality };
//
var masterLethalityTopMethod =
masterTop.Join(KongfuTop, m => m.masterKongfu, k => k.kongfuName, (m, k) =>
new { id = m.id, Name = m.Name, kongfu = m.masterKongfu, Level = m.Leverl, Kill = m.Leverl * k.Lethality })
.OrderByDescending(m => m.Kill);
foreach (var ma in masterLethalityTop)
{
Console.WriteLine(ma.Id + " " + ma.Name + " " + ma.kongfu + " " + ma.Lever + " " + ma.Kill + "\n");
}
foreach (var ma in masterLethalityTopMethod)
{
Console.WriteLine(ma.id + " " + ma.Name + " " + ma.kongfu + " " + ma.Level + " " + ma.Kill + "\n");
}
}
}
}
问题:$
$
符号在字符串前面告诉 C# 编译器:这个字符串是一个带插值的字符串,即字符串内部可以包含变量或表达式。
问题 lambda
总结:
-
为什么要用
.Select(x => new {...})
而不是Select(x)
: - 选择性返回字段:通过
Select(x => new {...})
你可以选择性地返回MartialArtsMaster
中的某些字段。例如,如果你只对Id
,Name
,Kungfu
,Level
等信息感兴趣,可以只选择这些字段,而不返回整个对象。 - 添加额外的属性:通过匿名类型,你还可以在查询中添加额外的属性,比如这里的
Top
,它是基于其他字段计算出来的一个额外字段。 - 避免暴露不需要的字段:如果你只关心某些字段,使用
Select
可以避免暴露整个对象的所有字段,减少不必要的数据传输。 Select(x => x)
会返回原始的MartialArtsMaster
对象,包含所有属性。Select(x => new { ... })
通过创建一个匿名类型,可以返回特定字段,还可以进行加工,比如计算排名等。
列表add
master.Add(new MartialArtsMaster() { Id = 1, Name = "黄蓉", Age = 18, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 9 });
分组
groupjoin
var mastergroup = kongfu.GroupJoin(master, k => k.kongfuName, m => m.Kungfu, (k, m) =>
new { k.kuongfuId, k.kongfuName, k.Lethality, Count = m.Count() })
.OrderByDescending(k => k.Count);
foreach (var kk in mastergroup)
{
Console.WriteLine(kk.kuongfuId+kk.kongfuName+kk.Lethality+kk.Count);
}
groupby
问题
1. from m in master
这部分指定了查询的源是 master
列表中的元素。每个元素 m
表示 MartialArtsMaster
类的一个实例。
2. group m by m.Menpai into g
这行代码是关键的分组操作:
group m by m.Menpai
:表示按照每个MartialArtsMaster
实例的Menpai
属性进行分组。into g
:这部分将分组结果命名为g
,它代表一个分组后的集合。每个分组都会包含一个Menpai
值及其对应的所有成员。
3. orderby g.Key
这部分是排序操作,作用是按 Menpai
(即分组的依据)对分组后的结果进行排序:
-
g.Key
:每个分组g
都有一个Key
,它就是该分组依据的值。在本例中,g.Key
对应的就是m.Menpai
(即门派名称)。所以,orderby g.Key
就是按门派名称(Menpai
)对分组结果进行升序排序。为什么要加上
orderby
呢?orderby g.Key
让查询的结果按照Menpai
字段排序。这样,可以确保结果按门派名称的字母顺序排列,易于查看。- 如果不加
orderby
,则返回的分组顺序将是不确定的,通常是根据原始数据中分组的顺序来排序的,但这种顺序可能会导致数据不易理解或处理。
groupby问题
var groupitems = from m in master
group m by m.Menpai into g
orderby g.Key
select new
{
menpai = g.Key,
Count = g.Count()
};
var groupmethod = master.GroupBy(m => m.Menpai, (k, m) => new { menpai = k, count = m.Count() });
(k, m) => new { menpai = k, count = m.Count() }
- 这是
GroupBy
的第二个参数,它是一个用于生成结果的投影(projection)函数。它的作用是为每个分组生成一个新的对象。k
:代表每个分组的键(即m.Menpai
的值),这就是分组的依据。在这个例子中,k
是每个Menpai
。m
:代表分组中的元素集合。它是一个集合,包含了所有具有相同Menpai
的master
元素。
3. menpai = k
- 在生成新的匿名对象时,
menpai = k
将分组的键k
赋值给menpai
属性。因为k
是我们用来分组的依据(即门派),所以menpai
就代表该分组的门派名称。
为什么 menpai = k
而不能使用 menpai = m.Menpai
?
-
原因:
m
在这里代表的是分组后的元素集合(即一组有相同Menpai
值的元素)。所以,m
是一个集合,不能直接使用m.Menpai
,因为m
是一个包含多个元素的集合,而不是单个元素。 -
k
是GroupBy
方法的分组键,它代表了当前分组的标识。在这个例子中,k
对应的是每个分组的Menpai
值,而这个值是每个分组的共同属性。因此,menpai = k
赋值给menpai
属性是正确的,它表示该分组的Menpai
。
如果你使用 menpai = m.Menpai
,会发生编译错误,因为 m
是一个集合(IEnumerable
类型),它本身并没有 Menpai
属性。你需要使用分组的键 k
来获取每个分组的 Menpai
属性。
量词
var any = master.Any(m => m.Menpai == "丐帮");
Console.WriteLine(any + "\n");
var all = master.All(m => m.Menpai == "丐帮");
Console.WriteLine(all + "\n");
var ouyangfeng = new MartialArtsMaster { Id = 1, Name = "黄蓉", Age = 18, Menpai = "丐帮", Kungfu = "打狗棒法", Level = 9 };
var huangrong = master[0];
var isouyangfeng = master.Contains(ouyangfeng);
var ishuangrong = master.Contains(huangrong as MartialArtsMaster);
Console.WriteLine(isouyangfeng +"\n");
Console.WriteLine(ishuangrong);
分页
int pageSize = 2;
int pageNum =(int) Math.Ceiling(master.Count() /(double) pageSize);
Console.WriteLine(master.Count + " " + pageNum + " " + pageSize + "\n");
for( i = 0; i < pageNum; i++)
{
var pageMaster = (from m in master
join k in kongfu on m.Kungfu equals k.kongfuName
orderby m.Level * k.Lethality descending
select new
{
m.Name,
m.Menpai,
m.Kungfu,
m.Level,
k.Lethality,
kill = m.Level * k.Lethality
}).Skip(i * pageSize).Take(pageSize);
Console.WriteLine("姓名 门派武功 杀伤力 修炼等级 总武力");
foreach(var m in pageMaster)
{
Console.WriteLine(m.Name + " " + m.Menpai + " " + m.Kungfu + " " + m.Lethality + " " + m.kill+"\n");
}
}
}
for (i = 0; i < pageNum; i++)
{
var pageMaster = master
.Join(kongfu, m => m.Kungfu, k => k.kongfuName,(m,k) => new
{
m.Name,
m.Menpai,
m.Kungfu,
m.Level,
k.Lethality,
kill = m.Level * k.Lethality
}).OrderByDescending(x => x.Level * x.Lethality)
.Skip(i * pageSize)
.Take(pageSize);
-
.Skip(i * pageSize)
:- 这个方法跳过查询结果中的前
i * pageSize
条记录。 i
表示当前页的索引,从 0 开始。pageSize
表示每页显示的记录数。- 所以,
.Skip(i * pageSize)
会跳过前面i * pageSize
条数据,以确保你从第i + 1
页开始加载数据。
- 这个方法跳过查询结果中的前
-
.Take(pageSize)
:- 这个方法会从跳过的记录之后,取出接下来的
pageSize
条记录。 - 这样,每一页就会获取到
pageSize
条数据。
- 这个方法会从跳过的记录之后,取出接下来的
集合
var itemintersect = (from m in master
where m.Menpai == "明教" || m.Menpai == "丐帮"
select m).Intersect(from m in master where m.Kungfu == "葵花宝典" select m);
var itemmethod = master.Where(m => m.Menpai == "明教" || m.Menpai == "丐帮")
.Intersect(master.Where(m => m.Kungfu == "葵花宝典"));
foreach( var m in itemmethod)
{
Console.WriteLine(m.Name + " " + m.Menpai + " "+ m.Kungfu);
}
合计
int[] arr = new int[] { 1, 2, 3, 4 };
int xx = arr.Aggregate((prod, n) => prod + n);
int y = arr.Aggregate(0, (prod, n) => prod + n);
int z = arr.Aggregate(0, (prod, n) => prod + n, r => r * 2);
Console.WriteLine(xx +" " + y+" " +z +" ");