Linq는 각 그룹별로, 그룹별로 정렬합니까?
다음과 같은 개체가 있습니다.
public class Student
{
public string Name { get; set; }
public int Grade { get; set; }
}
다음 쿼리를 만들고 싶습니다. 학생 이름으로 성적을 그룹화하고, 성적별로 각 학생 그룹을 정렬하고, 각 그룹에서 최대 성적을 기준으로 그룹을 정렬합니다.
따라서 다음과 같이 보일 것입니다.
A 100
A 80
B 80
B 50
B 40
C 70
C 30
다음 쿼리를 만들었습니다.
StudentsGrades.GroupBy(student => student.Name)
.OrderBy(studentGradesGroup => studentGradesGroup.Max(student => student.Grade));
그러나 그것은 반환 IEnumerable
IGrouping
되며 다른 foreach
쿼리 에서 그렇게 하고을 사용하여 다른 목록에 결과를 추가 하지 않는 한 내부 목록을 정렬 할 방법이 없습니다 AddRange
.
그렇게하는 더 예쁜 방법이 있습니까?
확실한:
var query = grades.GroupBy(student => student.Name)
.Select(group =>
new { Name = group.Key,
Students = group.OrderByDescending(x => x.Grade) })
.OrderBy(group => group.Students.First().Grade);
첫 번째 항목이 가장 높은 점수를받을 것이라는 것을 이미 알고 있기 때문에 주문 후 각 그룹 내에서 1 학년 만 쳐도됩니다.
그런 다음 다음과 같이 표시 할 수 있습니다.
foreach (var group in query)
{
Console.WriteLine("Group: {0}", group.Name);
foreach (var student in group.Students)
{
Console.WriteLine(" {0}", student.Grade);
}
}
투영없이 수행하는 방법 :
StudentsGrades.OrderBy(student => student.Name).
ThenBy(student => student.Grade);
각 그룹을 그룹의 정렬 된 버전에 매핑하는 추가 투영이 필요하다고 생각합니다.
.Select(group => group.OrderByDescending(student => student.Grade))
또한 일련의 그룹 대신 일련의 학생을 제공하는 또 다른 평면화 작업 이 필요할 수 있습니다 .
.SelectMany(group => group)
항상 프로젝션과 평면화를 수행 하는 단일 SelectMany
호출 로 둘 다 축소 할 수 있습니다 .
편집 : Jon Skeet이 지적했듯이 전체 쿼리에는 특정 비 효율성이 있습니다. 각 그룹을 정렬하여 얻은 정보는 그룹 자체의 순서에 사용되지 않습니다. 그룹 자체의 순서를 지정 하기 전에 각 그룹의 정렬을 이동하면 Max
쿼리를 더 간단한 First
쿼리 로 피할 수 있습니다 .
이 시도...
public class Student
{
public int Grade { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format("Name{0} : Grade{1}", Name, Grade);
}
}
class Program
{
static void Main(string[] args)
{
List<Student> listStudents = new List<Student>();
listStudents.Add(new Student() { Grade = 10, Name = "Pedro" });
listStudents.Add(new Student() { Grade = 10, Name = "Luana" });
listStudents.Add(new Student() { Grade = 10, Name = "Maria" });
listStudents.Add(new Student() { Grade = 11, Name = "Mario" });
listStudents.Add(new Student() { Grade = 15, Name = "Mario" });
listStudents.Add(new Student() { Grade = 10, Name = "Bruno" });
listStudents.Add(new Student() { Grade = 10, Name = "Luana" });
listStudents.Add(new Student() { Grade = 11, Name = "Luana" });
listStudents.Add(new Student() { Grade = 22, Name = "Maria" });
listStudents.Add(new Student() { Grade = 55, Name = "Bruno" });
listStudents.Add(new Student() { Grade = 77, Name = "Maria" });
listStudents.Add(new Student() { Grade = 66, Name = "Maria" });
listStudents.Add(new Student() { Grade = 88, Name = "Bruno" });
listStudents.Add(new Student() { Grade = 42, Name = "Pedro" });
listStudents.Add(new Student() { Grade = 33, Name = "Bruno" });
listStudents.Add(new Student() { Grade = 33, Name = "Luciana" });
listStudents.Add(new Student() { Grade = 17, Name = "Maria" });
listStudents.Add(new Student() { Grade = 25, Name = "Luana" });
listStudents.Add(new Student() { Grade = 25, Name = "Pedro" });
listStudents.GroupBy(g => g.Name).OrderBy(g => g.Key).SelectMany(g => g.OrderByDescending(x => x.Grade)).ToList().ForEach(x => Console.WriteLine(x.ToString()));
}
}
또는 다음과 같이 할 수 있습니다.
var _items = from a in StudentsGrades
group a by a.Name;
foreach (var _itemGroup in _items)
{
foreach (var _item in _itemGroup.OrderBy(a=>a.grade))
{
------------------------
--------------------------
}
}
참고URL : https://stackoverflow.com/questions/5013710/linq-order-by-group-by-and-order-by-each-group
'programing tip' 카테고리의 다른 글
여러 병을 결합하는 깨끗한 방법? (0) | 2020.12.03 |
---|---|
포스트 백에서 Page_Init 이벤트에서 어떤 컨트롤이 포스트 백을 유발하는지 어떻게 확인할 수 있습니까? (0) | 2020.12.03 |
Eclipse 프로그램에서 Java 키워드 어설 션을 활성화하는 방법은 무엇입니까? (0) | 2020.12.03 |
XML 헤더가 포함 된 경우 C # XmlDocument.LoadXml (string)이 실패하는 이유는 무엇입니까? (0) | 2020.12.03 |
XML 속성을 통해 클래스 이름을 어떻게 바꿀 수 있습니까? (0) | 2020.12.03 |