# 如何用linq在单一方法中制作聚合函数？[英] How to make aggregate function in single method using linq?

### 问题描述

```public class Student
{

public int Id { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string Nationality { get; set; }
}
{
A = 0,
B = 1,
C = 2,
D = 3,
E = 4
}

var list = new List<Student>();
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 });
```

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,
}).ToList();

//avg
var a = (from x in list.GroupBy(k => k.Gender)
select new
{
category = x.Key,
}).ToList();
```

## 推荐答案

```public class AggregateValue<T>
{
public string Category { get; set; }
public T Value { get; set; }
}
```

```    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 = 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 count = new Func<IEnumerable<Student>, int>(p => p.Count());

var c = GetAggregateValues(list, count);
```

## 其他推荐答案

```var result = (from x in list.GroupBy(k => k.Gender)
select new
{
category = x.Key,
Count = x.Count(),
}).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 string Nationality { get; set; }
}
{
A = 0,
B = 1,
C = 2,
D = 3,
E = 4
}

var list = new List<Student>();
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,
}).ToList();

//avg
var a = (from x in list.GroupBy(k => k.Gender)
select new
{
category = x.Key,
}).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 = 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 count = new Func<IEnumerable<Student>, int>(p => p.Count());

var c = GetAggregateValues(list, count);
```

## 其他推荐答案

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