问题描述
我有这样的课程
public class Student { public int Id { get; set; } public string Name { get; set; } public string Gender { get; set; } public GRADE Grade { get; set; } public string Nationality { get; set; } } public enum GRADE { A = 0, B = 1, C = 2, D = 3, E = 4 } var list = new List<Student>(); list.Add(new Student() { Id = 1, Name = "Prasad", Gender = "M", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 2, Name = "Raja", Gender = "M", Nationality = "India", Grade = GRADE.B }); list.Add(new Student() { Id = 3, Name = "Hindu", Gender = "F", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 4, Name = "Hamed", Gender = "M", Nationality = "India", Grade = GRADE.C }); list.Add(new Student() { Id = 5, Name = "Priya", Gender = "F", Nationality = "India", Grade = GRADE.D }); list.Add(new Student() { Id = 6, Name = "Meera", Gender = "F", Nationality = "India", Grade = GRADE.B });
我得到了这样的解决方案,对于我想要编写一堆代码的每个表达式.和,avg,count等
linq表达式
//count var c = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Value = x.Count() }).ToList(); //sum var s = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Value = x.Sum(k => (int)k.Grade) }).ToList(); //avg var a = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Value = x.Average(k => (int)k.Grade) }).ToList();
我正在尝试基于聚合函数进行一个函数;它应该返回值,我试过我找不到它.
推荐答案
一个问题是,您拥有的一个问题是,所有三个聚合都没有相同的返回类型,也是使用函数,那么返回类型必须是对象,因为您返回匿名类型.
我最接近的我认为你想要的是这个;
步骤1:创建新类型;
public class AggregateValue<T> { public string Category { get; set; } public T Value { get; set; } }
步骤2:创建一个返回此类型集合的函数,并接受Func作为将计算不同聚合的参数;
IEnumerable<AggregateValue<T>> GetAggregateValues<T>(List<Student> students, Func<IEnumerable<Student>, T> aggregateFunction) { return (from x in students.GroupBy(k => k.Gender) select new AggregateValue<T> { Category = x.Key, Value = aggregateFunction(x) }).ToList(); }
你可以像这样使用它;
var list = new List<Student>(); list.Add(new Student() { Id = 1, Name = "Prasad", Gender = "M", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 2, Name = "Raja", Gender = "M", Nationality = "India", Grade = GRADE.B }); list.Add(new Student() { Id = 3, Name = "Hindu", Gender = "F", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 4, Name = "Hamed", Gender = "M", Nationality = "India", Grade = GRADE.C }); list.Add(new Student() { Id = 5, Name = "Priya", Gender = "F", Nationality = "India", Grade = GRADE.D }); list.Add(new Student() { Id = 6, Name = "Meera", Gender = "F", Nationality = "India", Grade = GRADE.B }); var sumGrades = new Func<IEnumerable<Student>, int>(p => p.Sum(l => (int)l.Grade)); var aveGrades = new Func<IEnumerable<Student>, double>(p => p.Average(k => (int)k.Grade)); var count = new Func<IEnumerable<Student>, int>(p => p.Count()); var c = GetAggregateValues(list, count); var s = GetAggregateValues(list, sumGrades); var a = GetAggregateValues(list, aveGrades);
其他推荐答案
您可以在一个语句中组合所有汇总:
var result = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Count = x.Count(), Sum = x.Sum(k => (int)k.Grade), Average = x.Average(k => (int)k.Grade) }).ToList();
问题描述
I have class like this
public class Student { public int Id { get; set; } public string Name { get; set; } public string Gender { get; set; } public GRADE Grade { get; set; } public string Nationality { get; set; } } public enum GRADE { A = 0, B = 1, C = 2, D = 3, E = 4 } var list = new List<Student>(); list.Add(new Student() { Id = 1, Name = "Prasad", Gender = "M", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 2, Name = "Raja", Gender = "M", Nationality = "India", Grade = GRADE.B }); list.Add(new Student() { Id = 3, Name = "Hindu", Gender = "F", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 4, Name = "Hamed", Gender = "M", Nationality = "India", Grade = GRADE.C }); list.Add(new Student() { Id = 5, Name = "Priya", Gender = "F", Nationality = "India", Grade = GRADE.D }); list.Add(new Student() { Id = 6, Name = "Meera", Gender = "F", Nationality = "India", Grade = GRADE.B });
I got the solution like this, For each expression i want to write bunch of code.. Sum,Avg,Count etc
Linq Expressions
//count var c = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Value = x.Count() }).ToList(); //sum var s = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Value = x.Sum(k => (int)k.Grade) }).ToList(); //avg var a = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Value = x.Average(k => (int)k.Grade) }).ToList();
I am trying to make one function, based on the aggregate function; it should return the value, I tried I could not find it.
推荐答案
One issue you have is that all three aggregates do not have the same return type, also if you use a function then the return type would have to be object because you are returning an anonymous type.
The closest I could get to what I think you want was this;
Step 1: create a new type;
public class AggregateValue<T> { public string Category { get; set; } public T Value { get; set; } }
Step 2: Create a function that returns a collection of this type and accepts a Func as a parameter that will calculate your different aggregates;
IEnumerable<AggregateValue<T>> GetAggregateValues<T>(List<Student> students, Func<IEnumerable<Student>, T> aggregateFunction) { return (from x in students.GroupBy(k => k.Gender) select new AggregateValue<T> { Category = x.Key, Value = aggregateFunction(x) }).ToList(); }
You can use it like this;
var list = new List<Student>(); list.Add(new Student() { Id = 1, Name = "Prasad", Gender = "M", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 2, Name = "Raja", Gender = "M", Nationality = "India", Grade = GRADE.B }); list.Add(new Student() { Id = 3, Name = "Hindu", Gender = "F", Nationality = "India", Grade = GRADE.A }); list.Add(new Student() { Id = 4, Name = "Hamed", Gender = "M", Nationality = "India", Grade = GRADE.C }); list.Add(new Student() { Id = 5, Name = "Priya", Gender = "F", Nationality = "India", Grade = GRADE.D }); list.Add(new Student() { Id = 6, Name = "Meera", Gender = "F", Nationality = "India", Grade = GRADE.B }); var sumGrades = new Func<IEnumerable<Student>, int>(p => p.Sum(l => (int)l.Grade)); var aveGrades = new Func<IEnumerable<Student>, double>(p => p.Average(k => (int)k.Grade)); var count = new Func<IEnumerable<Student>, int>(p => p.Count()); var c = GetAggregateValues(list, count); var s = GetAggregateValues(list, sumGrades); var a = GetAggregateValues(list, aveGrades);
其他推荐答案
You can combine all your aggregations in one statement:
var result = (from x in list.GroupBy(k => k.Gender) select new { category = x.Key, Count = x.Count(), Sum = x.Sum(k => (int)k.Grade), Average = x.Average(k => (int)k.Grade) }).ToList();