GroupBy
Groupby
2024.9.13又在GPT的帮助下实现另一种去重方法:
prs = prs.GroupBy(p => p.name).Select(g => g.First()).ToList(); 实现了对prs中的对象按name去重。
原理:GroupBy后形成了一个两重List,最里层是每个相同name对应的List。后面的select表示对里层每个List的加工,Select(g => g.First())表示对每个里层List去第一个元素,Select(c=>c.Key)表示对每个里层List提取共同的分组属性
GroupBy对集合进行分组,结果是各子集的集合。后一般跟select取出分组信息,如,kes为KEY类型的对象集合
var k1 = kes.GroupBy(c => c.gpSm).Select(c=>c.Key).ToList(); //获得分组关键字的集合List<string或int等>
关键结构:GoupBy(...).Select(...).ToList()
var k2 = kes.GroupBy(c => c.gpSm).Select(c=>c.ToList()).ToList();//获得分组后子集形成的集合,类型为List<List<KEY>>;
//可以继续对子集进行分组,Group嵌套Group,最后连续3个ToList()缺一不可
var k3 = kes.GroupBy(c => c.gpSm).Select(c=>c.GroupBy(n=>n.ym).Select(m=>m.ToList()).ToList()).ToList(); //类型是List<List<List<KEY>>>;
对集合进行分组,如:
var dllList = _menuMan.Load(c => c.TXT_ASSEMBLYNAME != null).GroupBy(c=>c.TXT_ASSEMBLYNAME).OrderByDescending(c=>c.Count()).Select(c=>c.Key).ToList();
这里Goupby后面的OrderByDescending表示对每组数量按倒序排列,最后返回每组的Key,该Key为String型
如果没有最后的Select,Groupby的结果集是IGROUPING<string,XXXX>类型
也可通过Select返回匿名类型,如.Select(c=>new{c.Key,mx=c.Max(p=>p.price)}) //注意,对非值类型的匿名类型成员必须设置名称,如本例中的mx=...。
另外,GroupBy后面的Where相当于Having,对Key可以分拆开,与count,max等组成自定义返回类型,如
var fpk = _frcr.FindAll(c => true).GroupBy(c => new { f = c.father, p = c.pkcol }).Where(c => c.Count() > 1).Select(g=>new { g.Key.f,g.Key.p,c=g.Count()}).ToList();
此外,GroupBy后还可用Aggregate累加分组内的元素,类似Oracle的Wm.Concat函数,如
var pp=kk.GroupBy(c => c.IDLIN).Where(c => c.Count() > 1).
Select(g=>new { g.Key,
c =g.Count(),
v =g.Aggregate("",(m,n)=>m+
TaxiwayBLL.TransGeo3DTo2D(System.Text.Encoding.Default.GetString((Byte[])n.GEOLINE))+"\n"
)
}
).ToList();
group后,取得每个分组内部元素的方法,就在GroupBy后使用Select(n=>n.ToList())就行,例如:
List<List<ROUTE_SEGMENT_TS>> rgsLst = _allRouteSegs.GroupBy(c => c.ROUTE_UUID).Select(n=> n.ToList()).ToList();
而获得的每个子对象ROUTE_SEGMENT_TS,与分组前的总对象allRouteSegs仍是浅复制关系
Sum()的用法:
cgs.GroupBy(c => c.ID).Select(c => new
{
ID = c.Key,
MT = c.Sum(n => n.MT),
PR = c.Sum(n => (n.PR * n.MT) / c.Sum(m => m.MT)),
}
2022.11.17 分组后提取每组最大值形成新的List
b8=b8.GroupBy(c => c.JYTime.Substring(0, 7)).Select(c => c.ToList().Where(t=>t.JYTime==c.Max(n=>n.JYTime)).FirstOrDefault()).ToList();
分组后select(c=>c.ToList())形成两重List;.Where(t=>t.JYTime==c.Max(n=>n.JYTime))在内层List中获取每个List的JYTime最大值注意t、y、n三个代词;注意此时结构仍为两层List,最内层List的每个集合只有一个元素,要变成一层List结构只需用FirstOrDefault降维,而不能用ToList();最后形成与原来一直结构的单层LIst。