Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0038: Doppelte Einträge entfernen

 von 

Über den Tipp  

Dieser Vorschlag soll VB.NET Tipp 0042 ersetzen.

Dieser Tippvorschlag wird übernommen.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Algorithmen
  • Listensteuerelemente

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
listbox,bindinglist,databinding

Der Vorschlag wurde erstellt am: 03.09.2007 04:27.
Die letzte Aktualisierung erfolgte am 16.01.2009 17:15.

Zurück zur Übersicht

Beschreibung  

Auch beim Entfernen doppelter Einträge aus einer Listbox erweist es sich als vorteilhaft, nicht "am Control" zu programmieren, sondern an den Daten, und diese per Databinding ans Control zu binden.
(Anzumerken noch, daß das hier gelöste Problem gar nicht entstünde, würde man das Hinzufügen doppelter Einträge von vornherein unterbinden.)

Schwierigkeitsgrad

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [7,42 KB]

' Dieser Source stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!
'
' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird.
' In den Zip-Dateien ist er jedoch zu finden.

' ---------- Anfang Projektgruppe RemoveDoubles.sln ----------
' --------- Anfang Projektdatei RemoveDoubles.vbproj ---------
' ------------------ Anfang Datei Form1.vb  ------------------
Imports System.ComponentModel

Public Class Form1

    ' dient der Wiederherstellung des Anfangs-Zustandes
    Private _Template(2000) As Integer

    ' die zur Anzeige gebrachten Daten
    Private _UnderlayingData As New List(Of Integer)

    ' _DataSource wird als Wrapper um _UnderlayingData initialisiert. Die Bindinglist meldet
    ' direkte Änderungen sofort an die gebundenen Controls. Änderungen an _UnderlayingData
    ' dagegen werden nicht "bemerkt". Daher ist in _UnderlayingData eine viel schnellere
    ' Datenverarbeitung möglich, weil nicht bei jeder Veränderung die angebunden Controls
    ' benachrichtigt werden.
    Private _DataSource As New BindingList(Of Integer)(_UnderlayingData)

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load

        Dim rnd As New Random()

        For i As Integer = 0 To _Template.Length - 1
            _Template(i) = rnd.Next(0, 300)
        Next

        _UnderlayingData.AddRange(_Template)
        ListBox1.DataSource = _DataSource

    End Sub

    Private Sub Button_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _
              btRestoreSource.Click, btRemoveDoubles.Click, btSort.Click

        Select Case True

            Case sender Is btRestoreSource
                _UnderlayingData.Clear()
                _UnderlayingData.AddRange(_Template)

            Case sender Is btRemoveDoubles
                RemoveDoubles(_UnderlayingData)

            Case sender Is btSort

                ' Sortieren der Items macht vorhandene Doppelungen sofort sichtbar
                _UnderlayingData.Sort()

        End Select

        _DataSource.ResetBindings() ' angebundene Controls benachrichtigen

    End Sub

    Public Sub RemoveDoubles(Of T)(ByVal lst As List(Of T))

        ' Der Algorithmus ist eigentlich ganz unnötig auf Geschwindigkeit optimiert: Das
        ' hierauf folgende Zeichnen der Listbox wird ca. 500 - 1000 fach langsamer sein.
        ' (In VB2008 bietet übrigens die Extension-Method "Linq.Enumerable.Distinct()"
        ' vergleichbare Funktionalität.)
        Dim known As New Dictionary(Of T, Byte)
        Dim i As Integer = 0

        ' erste Doppelung suchen
        For i = 0 To lst.Count - 1

            Dim itm As T = lst(i)

            If known.ContainsKey(itm) Then Exit For
            known.Add(itm, 0)
        Next

        ' nach der ersten Doppelung wird der vorlaufende Zähler ii eingeführt, und
        ' unbekannte Items werden an die Position des jetzt nachlaufenden Zählers i kopiert
        For ii As Integer = i + 1 To lst.Count - 1

            Dim itm As T = lst(ii)

            If Not known.ContainsKey(itm) Then
                known.Add(itm, 0)
                lst(i) = itm
                i += 1
            End If

        Next

        lst.RemoveRange(i, lst.Count - i)

    End Sub

End Class

' ------------------- Ende Datei Form1.vb  -------------------
' ---------- Ende Projektdatei RemoveDoubles.vbproj ----------
' ----------- Ende Projektgruppe RemoveDoubles.sln -----------

	

Diskussion  

Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.
Folgende Diskussionen existieren bereits

Anmerkungen - Philipp Stephani 15.01.2009 22:58

Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.