vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Top-Preis! AP-Access-Tools-CD Volume 1  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Variablen/Strings · Array/ArrayList   |   VB-Versionen: VB.NET27.01.06
Instanzen in einer ArrayList sortieren (VB.NET)

Wie man Instanzen eigener Klassen sortiert, die in einer ArrayList stehen

Autor:   David MertnerBewertung:     [ Jetzt bewerten ]Views:  19.736 
ohne HomepageSystem:  WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11kein Beispielprojekt 

Neulich beim Programmieren hatte ich das Anliegen, Klasseninstanzen, die in einer ArrayList gespeichert waren, zu sortieren. Natürlich nicht irgendwie, sondern nach einem bestimmten Feld, das ich zur Compilezeit noch nicht kenne, das aber zur Ausführzeit bekannt wird.
Wie das funktioniert, zeige ich jetzt.

Die Testklasse heißt schlicht "Schiff":

<Serializable()> Public Class Schiff
  Implements IComparable ' (1)
 
  Public Name As String
  Public Heimathafen As String
  Public Baujahr As Integer
  Public Kaufpreis As Single
  Public Stapellauf As New Date
  Public Shared SortierFeld As String = "Heimathafen" ' (2)
  Public Shared Sortierung As SortOrder = SortOrder.Ascending
 
  Public Sub New(ByVal Name As String, ByVal Heimathafen As String, _
    ByVal Baujahr As Integer, ByVal Kaufpreis As Single, ByVal Stapellauf As Date)
 
    Me.Name = Name
    Me.Heimathafen = Heimathafen
    Me.Baujahr = Baujahr
    Me.Kaufpreis = Kaufpreis
    Me.Stapellauf = Stapellauf
  End Sub
 
  Public Sub New()
  End Sub
 
  Public Function CompareTo(ByVal obj As Object) _
    As Integer Implements System.IComparable.CompareTo ' (3)
 
    Dim s As Schiff
    s = CType(obj, Schiff)
    Dim f1 As Reflection.FieldInfo
    f1 = Me.GetType.GetField(Me.SortierFeld)
    Dim f2 As Reflection.FieldInfo
    f2 = s.GetType.GetField(Me.SortierFeld)
    Wert1 = f1.GetValue(Me)
    Wert2 = f2.GetValue(s)
    If Wert1 Is Nothing Or Wert2 Is Nothing Then Exit Function ' (4)
 
    ' (5)
    If f1.FieldType Is GetType(Integer) Or f1.FieldType Is GetType(Short) Or f1.FieldType Is GetType(Long) Then
      If Wert1 > Wert2 Then
        Return 1
      ElseIf Wert1 < Wert2 Then
        Return -1
      Else
        Return 0
      End If
    ElseIf f1.FieldType Is GetType(Double) Or f1.FieldType Is GetType(Single) Then
      If Wert1 > Wert2 Then
        Return 1
      ElseIf Wert1 < Wert2 Then
        Return -1
      Else
        Return 0
      End If
    ElseIf f1.FieldType Is GetType(String) Then
      Return String.Compare(Wert1, Wert2)
    ElseIf f1.FieldType Is GetType(Date) Then
      Return Date.Compare(Wert1, Wert2)
    ElseIf f1.FieldType Is GetType(Decimal) Then
      Return Decimal.Compare(Wert1, Wert2)
    ElseIf f1.FieldType Is GetType(DateTime) Then
      Return DateTime.Compare(Wert1, Wert2)
    End If
  End Function
End Class

(1): implements IComparable brauchen wir für das Überschreiben der "CompareTo"-Methode, die die Hauptarbeit beim Sortieren für uns erledigt.

(2): interessant sind hier die beiden "shared"-Variablen, mit denen wir nachher den Sortiervorgang steuern. Natürlich könnte man das ganze auch in einen Verwalter auslagern, aber der Einfachheit halber habe ich das gleich in der Klasse selber gemacht. In "SortierFeld" gibt man einfach den Namen des Feldes an, nach dem wir sortieren wollen. "Sortierung" gibt an, ob wir aufsteigend oder absteigend sortieren wollen, aber dazu später mehr.

(3): Das Herzstück der Sortierung ist diese Funktion, die wir über die Implementierung der Schnittstelle "IComparable" einfach überschreiben. Wir holen uns zuerst die Werte der beiden Felder, die wir über die Klassenvariable "Sortierfeld" bestimmt haben. (f1 und f2 sind Verweise auf die jeweiligen Klassenelemente) Man beachte, dass einer der Vergleichswerte in der aktuellen Instanz ruht (Me) und der andere von außen als Parameter kommt. Wir vergleichen also quasi das Haus des Nachbarn mit unserem eigenen

(4): falls eins der Felder nichts zurückgibt, dann steigen wir aus. Ein Grund hierfür wäre beispielsweise die Nicht-Existenz des Feldes! Dies kann vorliegen, falls in der ArrayList Instanzen von verschiedenen Klassen gespeichert sind.

(5): nun folgen die von uns implementierten Vergleiche. Ganzzahlvergleiche werden der Bequemlichkeit halber zusammengefasst. Hier kann man auch eigene Definitionen einbringen, etwa eine Rundung auf zwei Nachkommastellen bei single, vier bei double, Missachtung von negativem Vorzeichen oder dergleichen. Bei den komplexeren Datentypen verwenden wir einfach die bereits existierenden Compare-Methoden gemäß dem Prinzip des intelligenten Faulseins

Nun ein Beispiel zur praktischen Anwendung:

' Das einzige, was wir tun müssen, ist festzulegen, wonach wir
' sortieren wollen. Hier im Beispiel suchen wir uns einfach mal
' das Baujahr aus und wir wollen absteigende Resultate erhalten.
Private Sub Form1_Load(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load
 
  Schiff.SortierFeld = "Baujahr"
  Schiff.Sortierung = SortOrder.Descending
End Sub
 
' Diese Funktion wurde hier einem Steuerelement zugewiesen, nach dessen Klick
' der Code ausgeführt wird. (geht natürlich auch anders, etwa mit Hilfe eines
' eigenen Verwalters, der die Daten hält; sprengt jetzt aber vielleicht etwas den Rahmen)
Private Sub Sortieren_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Sortieren.Click
  ' Erstellen einiger Instanzen
  Dim s1 As New Schiff("Albatros", "Rostock", 1864, 492.9, New Date(1863, 3, 5))
  Dim s2 As New Schiff("Ubena von Bremen", "Bremen", 1380, 482.5, New Date(1379, 8, 27))
  Dim s3 As New Schiff("Adler von Lübeck", "Lübeck", 1565, 285.7, New Date(1563, 12, 9))
  Dim s4 As New Schiff("Rath von Riga", "Riga", 1341, 450.34, New Date(1340, 11, 24))
 
  ' Füllen der ArrayList mit den Schiffen
  Dim AL As New ArrayList
  AL.Add(s1)
  AL.Add(s2)
  AL.Add(s3)
  AL.Add(s4)
 
  AL.Sort()
  ' Das tolle bei der ganzen Sache ist, dass wir die eigentliche Sortierung
  ' nicht programmieren müssen, denn das kann die ArrayList ganz allein.
  ' Wir müssen lediglich sagen, nach welchen Gesichtspunkten zwei Instanzen
  ' unserer eigenen Klasse verglichen werden sollen.
  ' dies wiederum haben wir in der CompareTo-Methode schon gemacht.
  ' Die Arbeit des sortierens erfolgt intern mit Aufruf von "sort".
 
  If Schiff.Sortierung = SortOrder.Descending Then
    AL.Reverse() 'wir sortieren immer aufsteigend und drehen bei Bedarf um
  End If
 
  ' Ausgabe um zu sehen, was passiert ist
  Dim s As String
  s = AL.Item(0).Name & " " & AL.Item(0).Baujahr & "        " & _
    AL.Item(0).kaufpreis & vbNewLine
  s &= AL.Item(1).Name & " " & AL.Item(1).Baujahr & "        " & _
    AL.Item(1).kaufpreis & vbNewLine
  s &= AL.Item(2).Name & " " & AL.Item(2).Baujahr & "        " & _
    AL.Item(2).kaufpreis & vbNewLine
  s &= AL.Item(3).Name & " " & AL.Item(3).Baujahr & "        " & _
    AL.Item(3).kaufpreis & vbNewLine
  MsgBox(s)
End Sub

Dieser Tipp wurde bereits 19.736 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel