开发者

Multiple LINQ aggregate functions on different fields apply to the entire set

Can someone help me here with some hints. Basically I would like to apply different aggregate functions (Count, Sum, Min) on different fields to the entire set (not really groupping), and return the results as fields in an anonymous type. Something like:

var employees = new[] {
    new { Name = "John Smith", Gender="M", DateOfHiring=new DateTime(2004, 10, 22), Salary=60000 },
    new { Name = "Jane Smith", Gender="F", DateOfHiring=new DateTime(2008, 5, 22), Salary=55000 },
    new { Name = "Kathleen Smith", Gender="F", DateOfHiring=new DateTime(2006, 10, 22), Salary=75000 },
    new { Name = "David Smith", Gender="M", DateOfHiring=new DateTime(2002, 7, 12), Salary=85000 },
    new { Name = "Mary Smith", Gender="F", DateOfHiring=new DateTime(2009, 6, 15), Salary=55000 }
};

var query = from e in开发者_C百科 employees
             select new {
                NumberOfMaleEmployees = /* Count Where Gender = 'M' */,
                NumberOfFemaleEmployees = /* Count Where Gender = 'F' */,
                TotalSalaries = /* Sum All */,
                AverageSalary = /* Avg All */,
                LatestEmployee = /* Employee with Min DateOfHiring */
             };

Is it possible to achieve this in one query? Thanks in advance Iulian


While Mr. Skeet's answer works, it does cause employees to be iterated 5 times (including the "latest employee".) You're probably better off with a straight for loop that tracks each aggregation of interest:

int maleCount = 0;
int femaleCount = 0;
long totalSalary = 0;
double averageSalary = 0.0;
object latestEmployee = null;

for (int i = 0; i < employees.Length; i++)
{
    maleCount += (employees[i].Gender == "M") ? 1 : 0;
    totalSalary += employees[i].Salary;
    if (latestEmployee == null || employees[i].HireDate > latestEmployee.HireDate)
    {
        latestEmployee = employees[i];
    }   
}   

femaleCount = employees.Length - maleCount;
averageSalary = totalSalary / (double)employees.Length;

I've assumed that employees can be either male or female; you'd need to adjust your code if that assumption isn't warranted.


You don't want to be iterating over the array to start with by the looks of it - you just want:

var query = new {
    NumberOfMaleEmployees = employees.Count(x => x.Gender == "M"),
    NumberOfFemaleEmployees = employees.Count(x => x.Gender == "F"),
    TotalSalaries = employees.Sum(x => x.Salary),
    AverageSalary = employees.Average(x => x.Average),
};

The "latest employee" bit is slightly tricky - you basically want MaxBy from MoreLINQ, which would let you write:

LatestEmployee = employees.MaxBy(x => x.DateOfHiring)

(which you can include in the above query, of course).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜