[C#] Linq GroupBy op meerdere kolommen

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • ThaAresX
  • Registratie: September 2010
  • Laatst online: 09-10 08:52
Beste tweakeraars,

Ik wil een database tabel uitlezen en in een lijst zetten die gegroepeerd is. Met deze uiteindelijke lijst vul ik uiteindelijk weer een tabel met in de GUI. Alleen 2 kolommen moeten uniek zijn, anders moet er een nieuwe IGrouping worden aangemaakt.

Ik heb de volgende code om in ieder geval al op 1 kolom te sorteren.

C#:
1
2
3
4
5
6
7
8
9
10
public List<IGrouping<string, dbList>> GetGroupsFromDb(int id, SomeClass e) {
            SomeClass dbE = Db.dbList.Where(DbE => DbE.Id == e.Id).FirstOrDefault();
            List<IGrouping<string, dbList>> query = new List<IGrouping<string, dbList>>();

            if(dbE != null) {
                query = dbE.dbList.Where(p => p.id == id).GroupBy(p => p.FirstName, p => e).ToList();
            }
            
            return query;
        }


Ik heb al rondgekeken, en daar worden anonymous types gebruikt. Nou ben ik nieuw voor C# en weet ik niet precies hoe ik weer door de anonymous types IGrouping moet heen loopen voor de tabel.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
for (int i = 0; i < list.Count; i++) {
                Overview.RowCount += 1;
                Overview.RowStyles.Add(new RowStyle(SizeType.AutoSize, 25F));
                Overview.AutoSize = true;

                Label name = new Label() { Text = list[i].Key };
                Label lastName = new Label();
                Label kids = new Label();

                foreach (IGrouping<string, tblDefectDetailsSet> groupItem in defectList.Where(p => p.Key.Equals(name.Text.ToString()))) {
                    foreach (tblDefectDetailsSet s in groupItem) {
                        lastName.Text = s.LastName;
                        kids += s.Kids
                    }
                }

                kids.RightToLeft = System.Windows.Forms.RightToLeft.Yes;

                Overview.Controls.Add(name, 0, DefectOverview.RowCount - 1);
                Overview.Controls.Add(lastName, 1, DefectOverview.RowCount - 1);
                Overview.Controls.Add(kids, 2, DefectOverview.RowCount - 1);
            }


Er moet dus gesorteerd worden op voor- en achternaam. Zodat niet alle kinderen van de verschillende Peter's, Piet's, Klaas'sen bij elkaar opgeteld worden. Maar wel dat bij de combinatie van de voor en achternaam de kinderen bij elkaar opgeteld worden.

Kan iemand mij uitleggen hoe ik dit moet doen?

Alle reacties


Acties:
  • 0 Henk 'm!

  • Daos
  • Registratie: Oktober 2004
  • Niet online
De oplossing die je zelf al geeft met de anonieme typen werkt bij mij gewoon:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGroupBy
{
    class Person
    {
        public string givenName;
        public string familyName;
        public int age;

        public override string ToString()
        {
            return string.Format("{0} {1} aged {2}", givenName, familyName, age);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>
            {
                new Person { givenName = "Jan", familyName = "Jansen", age = 15 },
                new Person { givenName = "Jan", familyName = "Klaassen", age = 30 },
                new Person { givenName = "Klaas", familyName = "Jansen", age = 45 },
                new Person { givenName = "Jan", familyName = "Jansen", age = 60 },
            };

            var groups = persons.GroupBy(p => new { p.givenName, p.familyName });

            foreach (var gr in groups)
            {
                Console.WriteLine("Group:");
                foreach (var p in gr)
                {
                    Console.WriteLine(p);
                }
                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }
}


Uitvoer:
Group:
Jan Jansen aged 15
Jan Jansen aged 60

Group:
Jan Klaassen aged 30

Group:
Klaas Jansen aged 45

Acties:
  • 0 Henk 'm!

  • ThaAresX
  • Registratie: September 2010
  • Laatst online: 09-10 08:52
Daos schreef op maandag 11 januari 2016 @ 20:18:
De oplossing die je zelf al geeft met de anonieme typen werkt bij mij gewoon:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGroupBy
{
    class Person
    {
        public string givenName;
        public string familyName;
        public int age;

        public override string ToString()
        {
            return string.Format("{0} {1} aged {2}", givenName, familyName, age);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>
            {
                new Person { givenName = "Jan", familyName = "Jansen", age = 15 },
                new Person { givenName = "Jan", familyName = "Klaassen", age = 30 },
                new Person { givenName = "Klaas", familyName = "Jansen", age = 45 },
                new Person { givenName = "Jan", familyName = "Jansen", age = 60 },
            };

            var groups = persons.GroupBy(p => new { p.givenName, p.familyName });

            foreach (var gr in groups)
            {
                Console.WriteLine("Group:");
                foreach (var p in gr)
                {
                    Console.WriteLine(p);
                }
                Console.WriteLine();
            }

            Console.ReadKey();
        }
    }
}


Uitvoer:
Group:
Jan Jansen aged 15
Jan Jansen aged 60

Group:
Jan Klaassen aged 30

Group:
Klaas Jansen aged 45
Ik beweerde ook niet dat ie niet zou werken. Het was mij alleen onbekend hoe ik er dan overheen moest loopen om de gegevens eruit te krijgen. Nu wel, daarvoor bedankt! Maar bij mij is het doel om de totale leeftijd van Jan Jansen (15 + 60) te laten zien. Het slaat zo nergens op, maar het is een voorbeeld. Is het mogelijk om een Group in een Group te doen? Is geen mooie oplossing maar het zou wel doen wat ik zou willen.

Acties:
  • 0 Henk 'm!

  • Merethil
  • Registratie: December 2008
  • Laatst online: 21:27
ThaAresX schreef op dinsdag 12 januari 2016 @ 08:41:
[...]


Ik beweerde ook niet dat ie niet zou werken. Het was mij alleen onbekend hoe ik er dan overheen moest loopen om de gegevens eruit te krijgen. Nu wel, daarvoor bedankt! Maar bij mij is het doel om de totale leeftijd van Jan Jansen (15 + 60) te laten zien. Het slaat zo nergens op, maar het is een voorbeeld. Is het mogelijk om een Group in een Group te doen? Is geen mooie oplossing maar het zou wel doen wat ik zou willen.
Je kan toch zoiets doen?

C#:
1
2
3
4
5
6
7
8
9
10
11
foreach (var gr in groups)
{
    int age = 0;
    Console.WriteLine("Group:");
    foreach (var p in gr)
    {
        age += p.age;
    }
    Console.WriteLine("Aged: " + age);
    Console.WriteLine();
}


Uiteindelijk kan je natuurlijk van iedereen in die group gewoon data pakken en manipuleren zoals je wilt. Als je wilt kunnen filteren op de data terwijl je door de group heen looped moet het wel anders, maar dat is niet wat je eerst vroeg dus ben niet helemaal zeker wat je nou wilt doen.

[ Voor 5% gewijzigd door Merethil op 12-01-2016 08:48 ]


Acties:
  • 0 Henk 'm!

  • sig69
  • Registratie: Mei 2002
  • Nu online
Beter gebruik je .Sum()

Roomba E5 te koop


Acties:
  • 0 Henk 'm!

  • ThaAresX
  • Registratie: September 2010
  • Laatst online: 09-10 08:52
Ik heb nu dit:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var queryNestedGroups = from tblObject in List
                                        group tblObject by tblObject .FirstNameinto newGroup1
                                        from newGroup2 in
                                            (from tblObject in newGroup1
                                             group tblObject by tblObject .LastName)
                                        group newGroup2 by newGroup1.Key;

               foreach (var outerGroup in queryNestedGroups) {
                    Label name = new Label() { Text = outerGroup.Key };

                    foreach (var innerGroup in outerGroup) {
                        Label variation = new Label() { Text = innerGroup.Key };

                        Overview.RowCount += 1;
                        Overview.RowStyles.Add(new RowStyle(SizeType.AutoSize, 25F));
                        Overview.AutoSize = true;

                        Overview.Controls.Add(name, 0, Overview.RowCount - 1);
                        Overview.Controls.Add(variation, 1, Overview.RowCount - 1);

                        int sum = 0;
                        foreach (var innerGroupElement in innerGroup) {
                            sum += innerGroupElement.Sum;
                        }
                        Label quantity = new Label() { Text = sum.ToString() };
                        Overview.Controls.Add(quantity, 2, Overview.RowCount - 1);
                    }
                }


Volgende bug gevonden. Meer in de UI. De voornaam word maar 1x toegevoegd aan de de TableLayout, terwijl er wel 2x overheen geloopt wordt... Ik heb geen idee hoe ik dit moet oplossen? Iemand suggesties?

[ Voor 23% gewijzigd door ThaAresX op 12-01-2016 10:17 ]


Acties:
  • 0 Henk 'm!

  • ThaAresX
  • Registratie: September 2010
  • Laatst online: 09-10 08:52
Gefixt. Hele simpele oplossing, echt erg dat ik dat niet eerder had gezien.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var queryNestedGroups = from tblObject in List
                                        group tblObject by tblObject .FirstNameinto newGroup1
                                        from newGroup2 in
                                            (from tblObject in newGroup1
                                             group tblObject by tblObject .LastName)
                                        group newGroup2 by newGroup1.Key;

               foreach (var outerGroup in queryNestedGroups) {
                    
                    foreach (var innerGroup in outerGroup) {
                        Label variation = new Label() { Text = innerGroup.Key };
                        Label name = new Label() { Text = outerGroup.Key };


                        Overview.RowCount += 1;
                        Overview.RowStyles.Add(new RowStyle(SizeType.AutoSize, 25F));
                        Overview.AutoSize = true;

                        Overview.Controls.Add(name, 0, Overview.RowCount - 1);
                        Overview.Controls.Add(variation, 1, Overview.RowCount - 1);

                        int sum = 0;
                        foreach (var innerGroupElement in innerGroup) {
                            sum += innerGroupElement.Sum;
                        }
                        Label quantity = new Label() { Text = sum.ToString() };
                        Overview.Controls.Add(quantity, 2, Overview.RowCount - 1);
                    }
                }

Acties:
  • +1 Henk 'm!

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Zomaar een reactie negeren :N
C#:
1
2
3
4
int sum = 0;
foreach (var innerGroupElement in innerGroup) {
    sum += innerGroupElement.Sum;
}


kan je schrijven als

C#:
1
int sum = innerGroup.Sum(innerGroupElement => innerGroupElement.Sum);
Pagina: 1