C# 如何使用GroupBy()对多个项目进行分组?
考虑以下简化的对象和关系:C# 如何使用GroupBy()对多个项目进行分组?,c#,linq,group-by,C#,Linq,Group By,考虑以下简化的对象和关系: public class Job{ int JobId; String name; String status; Discipline disc; WorkCategory workCat; } public class Discipline { int DisciplineId; String DisciplineName; } public class Workcategory{ int WorkCategoryId;
public class Job{
int JobId;
String name;
String status;
Discipline disc;
WorkCategory workCat;
}
public class Discipline {
int DisciplineId;
String DisciplineName;
}
public class Workcategory{
int WorkCategoryId;
String WorkCategoryName;
}
public Class Grouping{
Discipline parent;
List<Workcategory> children;
}
编辑:
在发布了这篇文章之后,我意识到inital GroupBy参数会产生一组item,而我正在寻找group SubGroup结果
编辑2:
为了进一步澄清,我不希望相关作业作为结果的一部分,而是希望规程工作类别分组-因此,分组的原因是
类
基于@Obalix的初始解决方案 编辑2010年3月7日: 此解决方案不起作用-对象规程上的GroupBy将为每个对象生成唯一的分组。我认为这是因为它是一种引用类型。我说得对吗? 我最初接受这一点作为答案,但是在一些人意识到我的模拟数据本身是错误的之后。最初的问题仍然没有得到回答
var result = repository.GetJobsWithActiveStatus()
.GroupBy(x => x.disc)
.Select(g => new Grouping
{
Discipline = g.Key,
Catergories = g.GroupBy(x=>x.workCat) // <--- The Problem is here, grouping on a reference type
.Select(l=>l.Key) // needed to select the Key's only
.ToList()
});
var result=repository.getjobswitthactivestatus()
.GroupBy(x=>x.disc)
.选择(g=>新分组
{
纪律=钥匙,
Catergories=g.GroupBy(x=>x.workCat)//l.Key)//只需选择键的
托利斯先生()
});
如何实现分层分组机制
使用LINQ执行此操作的一般方法(如链接中所示)是:
编辑:在Ahmad的评论之后,这里是强类型版本:
var groupedList = list.GroupBy(x => x.disc)
.Select(g => new Grouping {
parent = g.Key,
children = g.GroupBy(x => x.workCat).ToList()
});
我会使用Linq语法:
var jobsByDiscipline =
from j in repository.GetJobsWithActiveStatus()
group j by j.Discipline.DisciplineID into g
select new {
DisciplineID = g.Key,
Jobs = g.ToList()
};
var jobsByCategory =
from j in repository.GetJobsWithActiveStatus()
group j by j.Workcategory.WorkcategoryID into g
select new {
WorkcategoryID = g.Key,
Jobs = g.ToList()
};
我发现这比很多带有lambda函数参数的链式方法更容易阅读
您可以通过以下方式获得分组:
var disciplineAndCategory =
from j in repository.GetJobsWithActiveStatus()
group j by j.Discipline.DisciplineID into g
let categories =
from j2 in g
select j2.Workcategory.WorkcategoryID
select new {
DisciplineID = g.Key,
Jobs = categories.Distinct() // each category id once
};
这里有另一种不需要分组类的方法
ILookup<Discipline, Workcategory> result = repository
.GetJobsWithActiveStatus()
.Select(job => new {disc = job.disc, workCat = job.workCat})
.Distinct()
.ToLookup(x => x.disc, x => x.workCat);
ILookup结果=存储库
.getjobswitthactivestatus()
.Select(job=>new{disc=job.disc,workCat=job.workCat})
.Distinct()
.ToLookup(x=>x.disc,x=>x.workCat);
这是适合我的解决方案
我首先需要获取所有规程组,然后创建关联的工作类别列表
在这两个世界是平等的
var result = liveJobs
.GroupBy(x => new {
x.disc.DisciplineID,
x.disc.DisciplineName
})
.Select(g => new Grouping()
{
parent = new Discipline(g.Key.DisciplineID,g.Key.DisciplineName),
children = g.Where(job=>job.disc.DisciplineID == g.Key.DisciplineID) // filter the current job discipline to where the group key disciplines are equal
.Select(j=>j.workCat)
.ToList()
});
+我同意,这种语法在分组时更容易阅读。@keith,谢谢你的建议,我第一次尝试使用它似乎很有效-但是没有经过测试,但是我更喜欢链式方法-我想是个人偏好:)我已经看了链接,读了评论后又看到了另一篇帖子,因此,我们将进一步了解这一点。但是,我正在寻找强类型结果(分组),然后您只需将
new{}
替换为new StrongType{}
。使用键
、计数
和工作类别组
的数据使用自定义成员。链接中描述的扩展方法是强类型的。仅供参考-上面答案中的帖子很棒-还有一篇关于Dynamic GroupByMany的后续帖子,如果有人感兴趣,我已经将其取消标记为答案-根据我的理解,对象上的选择和分组方式会为每个组合产生唯一的结果。即使我可以有两份工作,具有相同的学科和独特的工作理论,结果将产生两组。我认为这是因为对引用类型对象进行了比较。@Ahmad:回答你的问题时,我只能从你提供的信息中得出答案。你的解决方案与我的几乎相同——除了扩展分组——因此它会引导你找到正确的答案。拿走奖励是不好的,除非其他答案(不是你自己)从你提供的信息中提供了正确的结论。另外,每个海报都会添加一个最终帖子,并接受她/他自己的解决方案,从而拒绝奖励那些花时间引导他们找到最终解决方案的人。经过测试,结果与奥巴利克斯的答案类似。每个规程和工作类别的分组
var disciplineAndCategory =
from j in repository.GetJobsWithActiveStatus()
group j by j.Discipline.DisciplineID into g
let categories =
from j2 in g
select j2.Workcategory.WorkcategoryID
select new {
DisciplineID = g.Key,
Jobs = categories.Distinct() // each category id once
};
ILookup<Discipline, Workcategory> result = repository
.GetJobsWithActiveStatus()
.Select(job => new {disc = job.disc, workCat = job.workCat})
.Distinct()
.ToLookup(x => x.disc, x => x.workCat);
var result = liveJobs
.GroupBy(x => new {
x.disc.DisciplineID,
x.disc.DisciplineName
})
.Select(g => new Grouping()
{
parent = new Discipline(g.Key.DisciplineID,g.Key.DisciplineName),
children = g.Where(job=>job.disc.DisciplineID == g.Key.DisciplineID) // filter the current job discipline to where the group key disciplines are equal
.Select(j=>j.workCat)
.ToList()
});