NHead
NHead

Reputation: 129

Linq Get totals using group by

I have the following class:

class Item
{
    public decimal TransactionValue { get; set; }
    public string TransactionType { get; set; }
}

And I have this list:

        var items = new List<Item>
        {
            new Item
            {
                TransactionValue = 10,
                TransactionType = "Income"
            },
            new Item
            {
                TransactionValue = 10,
                TransactionType = "Income"
            },
            new Item
            {
                TransactionValue = -5,
                TransactionType = "Outgoing"
            },
            new Item
            {
                TransactionValue = -20,
                TransactionType = "Outgoing"
            }
        };

And I am trying to get the sums based on ValueType, I have tried the below but it is adding everything and giving me one total which is -5, what I want is totals for each transaction type so I want to get a new class which is Totals class below and with this data: TotalIncoming : 20 and TotalOutgoing : - 25.

        var r = items.Sum(x => x.TransactionValue);

class Totals
{
    public decimal TotalIncoming { get; set; }
    public decimal TotalOutgoing { get; set; }
}

Thanks

Upvotes: 0

Views: 114

Answers (2)

Rahul Singh
Rahul Singh

Reputation: 21825

You can achieve your desired result with following query:-

Totals result = new Totals
     {
        TotalIncoming = items.Where(x => x.TransactionType == "Income")
                             .Sum(x => x.TransactionValue),
        TotalOutgoing = items.Where(x => x.TransactionType == "Outgoing")
                             .Sum(x => x.TransactionValue)
     };

But, as you can see with your Type Totals, we need to hard-code the TransactionType and we have no clue from the result that this Sum belongs to which type apart from the naming convention used.

I will create the below type instead:-

class ItemTotals
{
   public string ItemType { get; set; }
   public decimal Total { get; set; }
}

Here we will have the TransactionType along with its corresponding Total in the result, we can simply group by TransactionType & calculate the sum, here is the query for same:-

List<ItemTotals> query = items.GroupBy(x => x.TransactionType)
                                          .Select(x => new ItemTotals
                                          {
                                              ItemType = x.Key,
                                              Total = x.Sum(z => z.TransactionValue)
                                          }).ToList();

Here is the Complete Working Fiddle, you can choose from both.

Upvotes: 1

Bradford Dillon
Bradford Dillon

Reputation: 1800

I'm sure there is a probably a clever way to do this in one line using Linq, but everything I could come up with was quite ugly so I went with something a bit more readable.

var results = items.GroupBy(x => x.TransactionType)
    .ToDictionary(x => x.Key, x => x.Sum(y => y.TransactionValue));

var totals = new Totals
{
    TotalIncoming = results["Income"],
    TotalOutgoing = results["Outgoing"]
};

Upvotes: 1

Related Questions