bwk4u
bwk4u

Reputation: 25

Can't think of a linq way to group my List in a desired way

So, i have my Model:

Card
Department
PayDate
State

And a List, with several items loaded:

1 , 25 , 12-20-2016 , A
1 , 25 , 12-20-2016 , B
1 , 25 , 12-21-2016 , D
1 , 30 , 12-20-2016 , A
1 , 30 , 12-20-2016 , X
2 , 10 , 12-20-2016 , B
2 , 15 , 12-20-2016 , A
2 , 15 , 12-21-2016 , E

I would like to group all that items and make a structure of this type:

Cards
   Card
      1
      Departments
         25
         PayDate
            12-20-2016
            State
               A
               B
            12-21-2016
            State
               D
         30
         PayDate
            12-20-2016
            State
               A
               X

......

It's like an XML tree, with parent tags and their childs (State is child of PayDate, PayDate child of Department, etc)..

Already tried messing with GroupBy(), Distinct() and nested foreach's, but i'm not able to reach my desired output. Is there any easy and efficient way to do this without going with a kind of a control break?

Upvotes: 0

Views: 78

Answers (1)

Kolichikov
Kolichikov

Reputation: 3020

Here's a quick way to solve this that should get you on your way. The basic idea is that calling GroupBy will group a list by a certain Key, while calling select will project the result of that select (you can think of it like the value), to a new object. You can then reapply the concept to each subgrouping to work your way down the list.

So for instance, list.GroupBy(x => x.Card) returns an IEnumerable of groups, and inside of each group is another IEnumerable of Models, but these Models all have the same Card. So We take an IEnumerable of all Models with the same card, and ask for a new Card object (again, I just used anonymous types here), and then we get the departments by grouping the remaining entries by departments, etc. etc, until you get to the end. Since State has no sublists, we just call pdd.Select(p => p.State), since we only care about the State value for the list of states.

I haven't made any classes for the sub types, but you will probably be doing something like Select(x=> new Department(x.Department)).

class Model
{
    public int Card;
    public int Department;
    public string PayDate;
    public char State;

    public Model(int c, int d, string p, char s)
    {
        Card = c;
        Department = d;
        PayDate = p;
        State = s;
    }
}
var list = new List<Model>
{
    new Model(1, 25, "12 - 20 - 2016", 'A'),
    new Model(1, 25, "12 - 20 - 2016", 'B'),
    new Model(1, 25, "12 - 21 - 2016", 'D'),
    new Model(1, 30, "12 - 20 - 2016", 'A'),
    new Model(1, 30, "12 - 20 - 2016", 'X'),
    new Model(2, 10, "12 - 20 - 2016", 'B'),
    new Model(2, 15, "12 - 20 - 2016", 'A'),
    new Model(2, 15, "12 - 21 - 2016", 'E')
};

var result = list.GroupBy(x => x.Card).Select(z => 
{
    return new
    {
        card = z.Key,
        departments = z.GroupBy(d => d.Department).Select(
            dd =>
            {
                return new
                {
                    department = dd.Key,
                    payDates = dd.GroupBy(pd => pd.PayDate)
                        .Select(
                            pdd =>
                            {
                                return new {paydate = pdd.Key, states = pdd.Select(p => p.State)};
                            })
                };
            })
    };
});

Upvotes: 1

Related Questions