如何使用LINQ - Sum和GroupBy对多个列表进行分组

时间:2015-04-08 19:07:44

标签: c# linq

我有三个通用列表,我正在尝试将它们组合成一个(List<One>)。我不知道如何在不同的列表上使用LINQ组。我想通过AccountCode,AccountDate和SalesCode进行分组;并总结金额。

public class One
{
    public string AccountCode { get; set; }

    public DateTime AccountDate { get; set; }

    public string SalesCode { get; set; }

    public decimal? Amount { get; set; }
}

public class Two
{
    public string AccountCode { get; set; }

    public DateTime AccountDate { get; set; }

    public string SalesCode { get; set; }

    public decimal? Amount { get; set; }
}   

public class Three
{
    public string AccountCode { get; set; }

    public DateTime AccountDate { get; set; }

    public string SalesCode { get; set; }

    public decimal? Amount { get; set; }
}   

List<One> oneList = new List<One>();
List<Two> twoList = new List<Two>();
List<Three> threeList = new List<Three>();

这是我的示例查询,但不起作用。注意:我没有包含List<Three>

from first in oneList
    join second in twoList
    on first.AccountCode equals second.AccountCode
    where
    (first.AccountDate.Date == second.AccountDate.Date && first.SalesCode == second.SalesCode)
     select new
     {
         first.AccountCode,
         first.AccountDate,
         first.SalesCode
         first.Amount,
         second.Amount
     }).Distinct()
                group bill by new { bill.AccountCode, bill.AccountDate, bill.SalesCode }
    into groupedList
    select new  
    {
        groupedList.Key.UAN,
        groupedList.Key.AccountDate,
        Amount = groupedList.Sum(a => a.Amount)
    };  

1 个答案:

答案 0 :(得分:2)

正如评论中所提到的,您需要的第一件事是常见类型,这样就可以将3个列表合并到一个列表中。这可能是我在这里展示的基类或接口。

public interface IAccount
{
    string AccountCode { get; set; }
    DateTime AccountDate { get; set; }
    string SalesCode { get; set; }
    decimal? Amount { get; set; }
}

public class One : IAccount 
{
    // ...
}

public class Two : IAccount 
{
    // ...
}

public class Three : IAccount 
{
    // ...
}

一旦到位,就可以很容易地将3个列表合并为一个:

var allList = oneList.Cast<IAccount>().Union(twoList).Union(threeList);

从那里,小组也变得更加简单。当使用LINQ按多个字段分组时,您需要一个IEqualityComparer类,如下所示:

public class AccountComparer : IEqualityComparer<IAccount>
{

    public bool Equals(IAccount x, IAccount y)
    {
        return x.AccountCode == y.AccountCode &&
            x.AccountDate == y.AccountDate &&
            x.SalesCode == y.SalesCode;
    }

    public int GetHashCode(IAccount obj)
    {
        return (obj.AccountCode + obj.AccountDate + obj.SalesCode).GetHashCode();
    }
}

按电话分组是一行:

var groups = allList.GroupBy(a => a, new AccountComparer());

或者,您可以创建一个只有3个关键字段的AccountKey类,并从keySelector lambda返回该字段。感觉有点干净,但代码更多。

从那里,你可以选择这样的总和:

var amountSums = from g in groups
    select new
    {
        g.Key.AccountCode,
        g.Key.AccountDate,
        g.Key.SalesCode,
        Amount = g.Sum(a => a.Amount)
    };