【问题标题】:How to make aggregate function in single method using linq?如何使用 linq 在单一方法中创建聚合函数?
【发布时间】:2016-05-22 07:15:37
【问题描述】:

我有这样的课

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 });

我得到了这样的解决方案,对于每个表达式我想写一堆代码.. Sum、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();

我正在尝试基于聚合函数创建一个函数;它应该返回值,我试过找不到。

【问题讨论】:

  • 如何将每个linq表达式放在一个方法中,然后用switch语句创建一个新方法,该方法将根据methods参数调用?
  • 我已经尝试在表达式中使用 switch 语句,这没有帮助..
  • 我不清楚你想要实现什么 - 你是什么意思“一个功能”?如果问题只是实现,您至少可以发布您期望如何使用此功能吗?
  • 查看聚合表达式,我写了三个 linq 表达式来获取数据...如果我想要一个静态函数,基于它应该返回的聚合...
  • Prasad 不清楚,我认为您正在尝试创建一个返回所有 sum/cout/avg 的聚合函数。值或一对一表示一个函数的一个聚合函数(即总和)。

标签: c# asp.net linq


【解决方案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);

【讨论】:

  • 您应该将AggregateValue 设为AggregateValue&lt;T&gt; 的泛型类型,这将是一个不错的解决方案。
  • 我已经编辑了我的答案,使 AggregateValue 成为通用类型,感谢 Enigmativity 的建议
【解决方案2】:

您可以在一个语句中组合所有聚合:

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();

【讨论】:

  • 不想在同一个表达式中返回所有聚合表达式..我想要一个静态函数,基于聚合函数它应该返回值
  • @PrasadRaja 你不能那样做,提供一部分 Linq 表达式作为参数比较复杂。
  • @PrasadRaja - 什么是“价值”?
  • 示例 Value = x.Sum(k => (int)k.Grade) , Value = x.Count() , Value = x.Average(k => (int)k.Grade)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-20
  • 1970-01-01
  • 1970-01-01
  • 2017-08-16
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多