List (Of Class) gruppieren und als List (Of Class) zurückgeben

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von hal2000.

    List (Of Class) gruppieren und als List (Of Class) zurückgeben

    Moin,


    eigentlich sagt der Titel schon alles.

    Die Klasse wäre in etwa so

    VB.NET-Quellcode

    1. Public Class Item
    2. Public Property AdresseID As Integer = 0
    3. Public Property AufKopfID As Integer = 0
    4. Public Property AufPosID As Integer = 0
    5. Sub New(ByVal AdresseID As Integer,
    6. Optional ByVal AufKopfID As Integer = 0,
    7. Optional ByVal AufPosID As Integer = 0)
    8. With Me
    9. .AdresseID = AdresseID
    10. .AufKopfID = AufKopfID
    11. .AufPosID = AufPosID
    12. End With
    13. End Sub
    14. End Class


    Im Code verwende ich diese as List (Of Item) und möchte nun nach AufKopfID gruppieren.

    VB.NET-Quellcode

    1. Dim Lst_AufKopf = Lst_IDs.GroupBy(Function(G) G.AufKopfID).ToList


    Allerdings erhalte ich dabei eine List (Of IGrouping(Of Integer, Item) zurück, hätte aber gerne eine List (Of Item).

    Weiter würde ich gerne das gruppierte Ergebnis (in Beispiel wären es AufKopfID 1 bis 6 die mir aus der Gruppierung zurückgegeben werden) direkt in eine List (Of Integer) schreiben.

    So würde es funktionieren, ist aber nicht besonders schön

    VB.NET-Quellcode

    1. Dim IDs As New List(Of Integer)
    2. For Each I In Lst_AufKopf
    3. IDs.Add(I.Key)
    4. Next


    Freundliche Grüße :)
    @BlueLagoonX Meinst Du Sortieren, wenn Du Gruppieren sagst?
    Dann mach Deine Item-Klasse so:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Item
    2. Implements IComparable(Of Item)
    3. Public Property AdresseID As Integer = 0
    4. Public Property AufKopfID As Integer = 0
    5. Public Property AufPosID As Integer = 0
    6. Sub New(ByVal AdresseID As Integer,
    7. Optional ByVal AufKopfID As Integer = 0,
    8. Optional ByVal AufPosID As Integer = 0)
    9. With Me
    10. .AdresseID = AdresseID
    11. .AufKopfID = AufKopfID
    12. .AufPosID = AufPosID
    13. End With
    14. End Sub
    15. Public Overrides Function ToString() As String
    16. Return String.Format("{0}-{1}-{2}", AufKopfID, AufPosID, AdresseID)
    17. End Function
    18. Public Function CompareTo(ByVal other As Item) As Integer Implements System.IComparable(Of Item).CompareTo
    19. Return Me.AufKopfID.CompareTo(other.AufKopfID)
    20. End Function
    21. End Class
    und zum Testen eine kleine GUI mit 2 Button und einer ListBox:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private MyList As New List(Of Item)
    3. Private Rnd As New Random
    4. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    5. Dim it = New Item(Rnd.Next(3), Rnd.Next(3), Rnd.Next(3))
    6. MyList.Add(it)
    7. Me.ListBox1.Items.Add(it)
    8. End Sub
    9. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    10. MyList.Sort()
    11. Me.ListBox1.Items.Clear()
    12. For Each Item In MyList
    13. Me.ListBox1.Items.Add(Item)
    14. Next
    15. End Sub
    16. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    ErfinderDesRades schrieb:

    naja
    Meist kommt dann noch ein zweites und drittes Kriterium dazu.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Sortieren wollte ich nicht, sondern wirklich gruppieren.

    Teil 1 gruppieren:
    Die Liste hat in Spalte AdresseID <10 verschiedene, AufKopfID 0 bis x und AufPosID 1 bis x

    Ich möchte schnell aus der Liste eine Gruppierung (als List Of Integer) über die Spalte AufKopfID haben

    VB.NET-Quellcode

    1. Dim Lst_AufKopf = Lst_IDs.GroupBy(Function(G) G.AufKopfID).ToList


    Damit hätte ich es gruppiert, Lst_AufKopf ist dann aber keine List (Of Item) mehr, sondern eine List (Of IGrouping())
    Wie bekomme ich die Gruppierte Liste in die Liste des selben Typs zurück?

    Teil 2, das Ausgeben der gruppierten AufKopfIDs in eine seperate List (Of Integer)

    Mit einer Schleife …

    VB.NET-Quellcode

    1. Dim Lst_IDs As New List(Of Integer)
    2. For Each A In Lst_AufKopf
    3. If Not Lst_IDs.Contains(A.AufKopfID) Then Lst_IDs.Add(A.AufKopfID)
    4. Next


    würde es funktionieren, schön ist es aber nicht

    BlueLagoonX schrieb:

    Ich möchte schnell aus der Liste eine Gruppierung (als List Of Integer) über die Spalte AufKopfID haben

    VB.NET-Quellcode

    1. Dim Lst_AufKopf = Lst_IDs.GroupBy(Function(G) G.AufKopfID).ToList

    Damit hätte ich es gruppiert, Lst_AufKopf ist dann aber keine List (Of Item) mehr
    Dassis unklar.
    Soll nun eine List(Of Item) bei rauskommen oder eine List(of Integer)?
    Mit .cast(of T) erzielt man das was gewünscht ist.


    Schau dir bitte das mal an.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Public Module Module1
    4. Private ReadOnly Rand As New Random
    5. Public Sub Main()
    6. Dim size = 10I
    7. Dim lstitems = CreateRngItems(size)
    8. 'Auf 'AufKopfID' gruppieren
    9. Dim ak = lstitems.GroupBy(Function(g) g.AufKopfID)
    10. 'Nun entspricht der Index dem Key
    11. Dim res = GetGroupItemKey(ak)
    12. Stop
    13. End Sub
    14. Private Function GetGroupItemKey(itemsort As IEnumerable(Of IGrouping(Of Int32, Item))) As Item()()
    15. If itemsort.Count > 0 Then
    16. 'sortieren
    17. itemsort = itemsort.OrderBy(Function(k) k.Key).ToArray
    18. Dim res = New Item(itemsort.Last.Key)() {}
    19. For i As Int32 = 0 To itemsort.Count - 1
    20. For j As Int32 = i To itemsort.Count - 1
    21. If itemsort(j).Key > itemsort(i).Key Then Exit For
    22. If itemsort(i).Key = itemsort(j).Key Then
    23. 'Casten einer Gruppe in einem Zug und
    24. 'zuweisen in eine Array
    25. res(itemsort(i).Key) = itemsort(j).Cast(Of Item).ToArray
    26. Exit For
    27. End If
    28. Next
    29. Next
    30. Return res
    31. End If
    32. Return Nothing
    33. End Function
    34. Private Function CreateRngItems(size As Int32) As List(Of Item)
    35. Dim res = New Item(size - 1) {}
    36. With Rand
    37. Return res.Select(Function(x) New Item(.Next(0, 100),
    38. .Next(0, size),
    39. .Next(0, 50))).ToList
    40. End With
    41. End Function
    42. End Module
    43. Public Class Item
    44. Public Property AufPosID As Integer = 0
    45. Public Property AdresseID As Integer = 0
    46. Public Property AufKopfID As Integer = 0
    47. Sub New(ByVal AdresseID As Integer,
    48. Optional ByVal AufKopfID As Integer = 0,
    49. Optional ByVal AufPosID As Integer = 0)
    50. With Me
    51. .AdresseID = AdresseID
    52. .AufKopfID = AufKopfID
    53. .AufPosID = AufPosID
    54. End With
    55. End Sub
    56. End Class


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „exc-jdbi“ ()

    Was du in Post 5 beschrieben hast macht keinen Sinn, denn:
    - Du gruppierst Objekte, schmeißt die Gruppen danach aber weg, um nur deren Indizes zu nutzen.
    - Die Gruppenindizes sind bereits eindeutig - es kann keine doppelten Gruppen-IDs geben. Trotzdem sucht deine Schleife in Schritt 2 nach Duplikaten.

    Was du vermutlich willst ist eine sehr komplizierte Umsetzung von lst.Select(Function(i) i.AufKopfID).Distinct(). Das ergibt eine List(Of Integer) aller AufKopfIDs ohne Duplikate. Dieselbe Operation kann man auch als Gruppierung formulieren, ist aber sinnlos: lst.GroupBy(Function(i) i.AufKopfID).Select(Function(grp) grp.Key)
    Gruß
    hal2000