简体   繁体   中英

Linq Dynamic Expressions Groupby with sum

I cannot figure out how to do a Linq.Dynamic on an ObservableCollection and sum some fields. Basically I want to do this;

var group
     from x in MyCollection
     group x by x.MyField into g
     select new MyClass
     {
         MyField = g.Key,
         Total = g.Sum(y => y.Total)
     };

Figured it would be this in Linq.Dynamic;

var dGroup = MyCollection
             .GroupBy("MyField ", "it")
             .Select("new (it.Key as MyField , it as new MyClass { Total  = sum(it.Total ) })");

However this keeps give me errors.

FYI MyCollection is a ObservableCollection<MyClass>

Edit:

I am sorry did not make this very clear. The reason I need it to be Linq.Dynamic is that the actual MyClass has about 10 properties that user can pick to group the collection MyCollection in. To make matters worse is the user can select multiple grouping. So hand coding the groups isn't an option. So while @Harald Coppoolse does work it requires that myClass.MyField to be hand coded.

So MyCollection is a sequence of MyClass objects, where every MyClass object has at least two properties: MyField and Total .

You want the sum of all Total values that have the same value for MyField

For example:

MyField  Total
   X       10
   Y        5
   X        7
   Y        3

You want a sequence with two elements: one for the X with a grand total of 10 + 7 = 17; and one for the Y with a grand total of 5 + 3 = 8

In method syntax:

var result = MyCollection.Cast<MyClass>()      // take all elements of MyCollection
    .GroupBy(myClass => myClass.MyField)       // Group into groups with same MyField
    .Select(group => new MyClass()             // for every group make one new MyClass object
    {
        MyField = group.Key,
        Total = group                          // to calculate the Total:
            .Select(groupElement => groupElement.Total) // get Total for all elements in the group
            .Sum(),                                     // and sum it
    })

If your ObservableCollection is in fact an ObservableCollection<MyClass> than you won't need the Cast<MyClass> part.

There is a lesser known GroupBy overload that will do this in one statement. I'm not sure if this one will improve readability:

var result = MyCollection.Cast<MyClass>()   // take all elements of MyCollection
    .GroupBy(myClass => myClass.MyField,    // group into groups with same MyField
        myClass => myClass.Total,           // for every element in the group take the Total
        (myField, totals) => new MyClass()  // from the common myField and all totals in the group
        {                                   // make one new MyClass object
            MyField = myField,              // the common myField of all elements in the group
            Total = totals.Sum(),           // sum all found totals in the group
        });

So this might not be the best way, but it is the only I found. FYI it more manual work than standard LINQ.

Here is the new Dynamic Linq;

var dGroup = MyCollection
         .GroupBy("MyField ", "it")
         .Select("new (it.Key as MainID, it as MyClass)");

The next problem is not only do you need to iterate through each MainID but you need to iterate through MyClass and sum for each MainID ;

foreach (dynamic r in dGroup)
{
        foreach (dynamic g in r.MyClass)
        {
               gTotal = gTotal + g.Total;
        }
 }

If someone can show me a better way to do this I will award the correct answer to that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM