9

I have these two classes in my code and a List of Class2. I want to group the list elements by date and ID using LINQ.

public class Class1
{
    public string ID;
    public int y;
    public int z;
}

public class Class2 
{
    public List<Class1> a;
    public int p, q;
    public string s;
    public DateTime date;
}

My list is similar to this:

List<Class2> object1 = new List<Class2>
{
    new Class2 {p = 5, q = 6, date = DateTime.Now, a = new List<Class1> { new Class1 { ID = "3643746HDJ", y = 0, z = 9 }, new Class1 { ID = "746327846HDJ", y = 0, z = 9 } } },
    new Class2 {p = 5, q = 6, date = DateTime.Now.AddDays(1), a = new List<Class1> { new Class1 { ID = "3643746HDJ", y = 0, z = 9 }, new Class1 { ID = "746327846HDJ", y = 0, z = 9 } } },
    new Class2 {p = 5, q = 6, date = DateTime.Now.AddDays(2), a = new List<Class1> { new Class1 { ID = "3643746HDJ", y = 0, z = 9 }, new Class1 { ID = "746327846HDJ", y = 0, z = 9 } } },
    new Class2 {p = 5, q = 6, date = DateTime.Now.AddDays(3), a = new List<Class1> { new Class1 { ID = "3643746HDJ", y = 0, z = 9 }, new Class1 { ID = "746327846HDJ", y = 0, z = 9 } } },
};

Sorry if this is a stupid question, but I am a beginner in C# programming and LINQ and I am not sure if this is even possible.

This is what I have tried based on examples I saw on the web but its not correct

var newList = from item in object1
              group new
              {
                  item.s,
                  item.a[0].x, //I think its wrong because of this
                  item.a[0].y  //and this
              }
              by new
              {
                  item.date,
                  item.a[0].ID  //and this
              }
              into temp
              select temp;

Since I have hardcoded index 0 in the grouping I am missing a lot of elements in my final list. How can I do this for all elements of list a in Class2?

Expected output is similar to this:

Key: {date: 19-09-2017 ID: 3643746HDJ}, Element: {{s: "abc", y = 1, z = 2}, {s: "pqr", y = 2, z = 4}, {s: "abc", y = 1, z = 2}}
Key: {date: 20-09-2017 ID: 3643746HDJ}, Element: {{s: "pop", y = 1, z = 2}, {s: "dfr", y = 2, z = 4}, {s: "abc", y = 1, z = 2}}
Key: {date: 19-09-2017 ID: 746327846HDJ}, Element: {{s: "abc", y = 7, z = 8}, {s: "asar", y = 2, z = 111}, {s: "abc", y = 1, z = 2}}
Key: {date: 20-09-2017 ID: 746327846HDJ}, Element: {{s: "abc", y = 7, z = 8}, {s: "asar", y = 2, z = 111}, {s: "abc", y = 1, z = 2}}
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Anon
  • 133
  • 1
  • 9
  • 1
    Do your classes actually look like that? Like are you using public fields instead of properties? – maccettura Sep 18 '17 at 19:04
  • 5
    Can you show expected output? – Fabio Sep 18 '17 at 19:04
  • Which `List` elements? How do you expect to group by `ID` when you have multiple `ID`s in the `List a`? – NetMage Sep 18 '17 at 19:07
  • 1
    This isn't really related to your issue, but I highly recommend taking a look at [this](https://stackoverflow.com/a/1180870/7662085) thread on why you should use auto properties instead of public fields. – stelioslogothetis Sep 18 '17 at 19:09
  • 2
    `item.a[0].p` - for items in `a` there is no `p` property (or `q`)... do you mean x and y – Gilad Green Sep 18 '17 at 19:09
  • @stybl I am using auto properties in my code but I didn't want to post my actual code here so I just created these examples classes which are similar to the actual class. – Anon Sep 18 '17 at 19:18
  • @GiladGreen yes I meant x and y. Will edit it now. – Anon Sep 18 '17 at 19:18
  • 2
    @Anon typically it really _helps_ us when your code is as 1 to 1 as possible. Omitting things like that could make it _harder_ for us to help. – maccettura Sep 18 '17 at 19:19
  • @Anon - cool :) thought so. See below – Gilad Green Sep 18 '17 at 19:21

1 Answers1

3

Your question states:

Since I have hardcoded index 0 in the grouping I am missing a lot of elements in my final list. How can I do this for all elements of list a in Class2?

As you want all the items from the nested collections you need to flatten the nested collections before grouping. In query syntax do so using another from:

var result = from item in object1
             from nested in item.a
             group new { item.s, nested.y, nested.z } by new { item.date, nested.ID } into g
             select g;

As each nested object does not have a p and q properties but your code shows accessing the nested items I used y and z instead

This can also be done using method syntax. To flatten the nested collections use SelectMany. For the GroupBy you can use the overload where you specify both key and element selector. General idea for that:

var result = object1.SelectMany(item => item.a.Select(nested => new {item, nested }))
                    .GroupBy(key => new { key.item.Date, key.nested.Id },
                             val => new { val.item.s, val.nested.x, val.nestd.y });

Even though it seems it is only for question purposes only I recommend giving meaningful names for properties and variables and to have a look at:

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • Great! This does exactly what I wanted. Thanks for helping and for these links. I'll start following these conventions from now. – Anon Sep 18 '17 at 19:33