Как сгруппировать несколько элементов с помощью GroupBy ()?
рассмотрим следующие упрощенные объекты и отношения:
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;
}
выше моделирует отношения, которые Job
связан с Discipline
и WorkCategory
. The Workcategory
всегда является ребенком конкретного родителя Discipline
(один ко многим). Можно предположить, что связь назначенной дисциплины и рабочей категории всегда будет допустимой.
проблема я столкнулся-это когда я пытаюсь создать Grouping
объект результат, основанный на фильтры, применяемые к Jobs
. Я не уверен, что это можно сделать или если подход, который я принимаю, даже правильный. Сам по себе точный вопрос мне не ясен, однако вышеизложенное определяет постановку проблемы.
- можно улучшить?
- как я могу группа заданий по дисциплине и Workcategory?
- мне нужно
Grouping
класса?
я пробовал следующее (Это моя первая попытка использовать Linq), но никакого успеха, поскольку мое понимание недостаточно полное. Другая альтернатива-сначала получить Discipline
группа и цикл через исходную группировку подбирая связанные Workcategory
.
var grouping = repository.GetJobsWithActiveStatus()
.GroupBy(x => new {
x.Discipline.DisciplineID,
x.Discipline.DisciplineName,
x.Category.WorkCategoryID,
x.Category.WorkCategoryName
})
.Select(g => new Grouping{
Discipline = new Discipline{
DisciplineID = g.Key.DisciplineID,
Name = g.Key.DisciplineName
},
Categories = ?? // this is where I am lost
}});
изменить: После публикации этого я понял, что параметры inital GroupBy приводят к одной группе элементов, тогда как я ищу результат Group-SubGroup.
редактирование 2:
Чтобы уточнить немного дальше, я не хочу, чтобы связанные задания были частью результата, а скорее Дисциплина-группировка Workcategory-таким образом, причина Grouping
класс
начальное решение на основе @Obalix
Редактировать 7-Mar-2010:
это решение не работает-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()
});
4 ответов
Вот описание как можно реализовать механизм иерархической группировки.
общий способ сделать это с помощью LINQ (как показано в ссылке):
var list = new List<Job>();
var groupedList = list.GroupBy(x => x.disc)
.Select(g => new {
Key = g.Key,
Count = g.Count(),
WorkCategoryGroups = g.GroupBy(x => x.workCat)
});
однако ссылка также описывает альтернативный способ, который позволяет вам сделать следующее:
var groupedList = list.GroupByMany(x => x.disc, x => x.workCat);
Edit: после комментария Ахмада вот строго типизированная версия:
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()
};
Я считаю, что легче читать, чем множество цепных методов с параметрами лямбда-функции.
Вы можете получить свои группировки из этого:
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);
Это решение, которое работает для меня.
Мне нужно, чтобы получить все дисциплины группы, а затем создать связанные списки workcategory где disciplineID равны.
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()
});