Mischen einer List of integer

  • VB.NET

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Mischen einer List of integer

    Guten Tag!
    Hier im Forum fand ich eine Möglichkeit, ein Array of Integer nach dem Zufall zu mischen:

    VB.NET-Quellcode

    1. Dim a2(48) As Integer
    2. For i As Integer = 1 To 49
    3. a2(i - 1) = i
    4. Next
    5. Dim a3(48) As Double
    6. Dim r2 As New Random
    7. For i As Integer = 1 To 49
    8. a3(i - 1) = r2.NextDouble
    9. Next
    10. Array.Sort(a3, a2)
    11. For i = 0 To 5
    12. ListBox1.Items.Add(Format(a2(i), "00"))
    13. Next


    Nun habe ich versucht, das gleiche mit einer List of integer durchzuführen, aber es will mir nicht so recht gelingen.
    Hier mein Versuch:

    VB.NET-Quellcode

    1. Dim a5 As New List(Of Integer)
    2. For i As Integer = 1 To 49
    3. a5.Add(i)
    4. Next
    5. Dim a4(48) As Integer ' As New List(Of Integer) ' es gelingt weder mit einem Array noch mit einer Liste
    6. Dim r3 As New Random
    7. For i As Integer = 1 To 49
    8. a4(i) = (r3.Next)
    9. ' a4.add(r2.next)
    10. Next
    11. a5.Sort(CType(a4, Global.System.Collections.Generic.IComparer(Of Integer))) ' ???????
    12. For i = 0 To 5
    13. ListBox1.Items.Add(Format(a5(i), "00"))
    14. Next


    Aber die Beschreibung des erforderlich IComparers will mir nicht gelingen.

    Kann mir jemand helfen? Vielen Dank!
    Freundliche Grüße!
    el
    Probier's mal hiermit:

    VB.NET-Quellcode

    1. ' System.Security.Cryptography importieren
    2. <System.Runtime.CompilerServices.Extension> _
    3. Public Shared Sub Shuffle(Of T)(list As IList(Of T))
    4. Dim provider As New RNGCryptoServiceProvider()
    5. Dim n As Integer = list.Count
    6. While n > 1
    7. Dim box As Byte() = New Byte(0) {}
    8. Do
    9. provider.GetBytes(box)
    10. Loop While Not (box(0) < n * ([Byte].MaxValue / n))
    11. Dim k As Integer = (box(0) Mod n)
    12. n -= 1
    13. Dim value As T = list(k)
    14. list(k) = list(n)
    15. list(n) = value
    16. End While
    17. End Sub
    Dieses Sub fügst du einfach in eine beliebige Klasse ein, dann kannst du es so anwenden:

    VB.NET-Quellcode

    1. Dim a5 As New List(Of Integer)
    2. For i As Integer = 1 To 49
    3. a5.Add(i)
    4. Next
    5. a5.Shuffle()

    stackoverflow.com/questions/27…domize-a-listt-in-c-sharp
    Hallo Haiyyu!!
    Herzlichen Dank! Es klappt vorzüglich! Ich musste die Sub shuffle in ein Modul auslagern und "shared" streichen.
    Der Code ist für mich Anfänger natürlich eine sehr schwer verdauliche Kost, da werde ich lange daran knabbern müssen, bis ich es kapiert habe, was das vor sich geht.

    Es ist dies aber doch eine andere Lösung als mit a.sort(????). Wie müsste den hier dieser "Global.System.Collections.Generic.IComparer(Of Integer)" aussehen?

    Nochmals danke sehr! :)
    el
    Oh, wusste nicht, dass Erweiterungsmethoden in VB.NET in Modulen sein müssen. ;)

    Bei Sort musst du eine Instanz einer Klasse, die IComparer(Of Integer) implementiert, übergeben.
    Lies dich am besten im MSDN dazu ein.

    Der Code implementiert übrigens einen Algorithmus, wie der funktioniert, weiß ich selber nicht. :P
    Aufruf: Zahlen.Shuffle()

    VB.NET-Quellcode

    1. Module erweiterung
    2. <System.Runtime.CompilerServices.Extension()>
    3. Sub Shuffle(Of t)(x As List(Of t))
    4. x.Sort(New shufflecomparer(Of t))
    5. End Sub
    6. Class shufflecomparer(Of t)
    7. Implements IComparer(Of t)
    8. Dim r As New Random
    9. Public Function Compare(x As t, y As t) As Integer Implements System.Collections.Generic.IComparer(Of t).Compare
    10. 'Hier werden normalerweise X und Y miteinander verglichen.
    11. Return r.Next(-1, 2)
    12. End Function
    13. End Class
    14. End Module


    Der Comparer(of T) implementiert das Interface IComparer (Zeile 7) Dadurch wird die Function in Zeile 9 generiert, die du dann mit Leben füllst. Im Normalfall wird hier X und Y von dir verglichen. Je nachdem, was größer ist, gibt diese Funktion dann -1, 1 oder 0 zurück. In diesem Fall wird dieser Wert durch eine Zufallszahl ermittelt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „der_Kurt“ () aus folgendem Grund: unnötiges 'ByRef' entfernt

    picoflop hat sein Teil doch schon viel pointierter formuliert gehabt (ich finds jetzt blos nimmer):

    VB.NET-Quellcode

    1. Dim rnd As New Random
    2. Dim shuffled = (From i In Enumerable.Range(0, 9) Order By rnd.Next).ToList


    Am performantesten ist aber wohl der Fisher-Yates-shuffle - hier meine Version:

    VB.NET-Quellcode

    1. Private rnd As New Random()
    2. Private Sub Shuffle(ByVal lst As System.Collections.IList)
    3. For i As Integer = 1 To lst.Count - 1
    4. Swap(lst, i, Rnd.Next(i + 1))
    5. Next
    6. End Sub
    7. Public Sub Swap(ByVal lst As IList, ByVal i1 As Integer, ByVal i2 As Integer)
    8. Dim tmp As Object = lst(i1)
    9. lst(i1) = lst(i2)
    10. lst(i2) = tmp
    11. End Sub

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hallo und Danke beiden Experten.
    Noch eine Frage zu dem Code von der_Kurt:

    VB.NET-Quellcode

    1. Public Function Compare(x As t, y As t) As Integer Implements System.Collections.Generic.IComparer(Of t).Compare
    2. 'Hier werden normalerweise X und Y miteinander verglichen.
    3. Return r.Next(-1, 2)

    Wenn ich versuche x und y miteinander zu vergleichen, kommt die Fehlermeldung, dass > < keine Operatoren für den Typ t sind. Meine Versuche, t durch integer zu ersetzen oder mit ctype, cint schlugen fehl. Was ist den t überhaupt für ein Typ? und wie würde denn dann so ein Vergleich zwischen x und y geschrieben werden müssen?
    Danke für Eure Gedult!
    el
    Der Code ist schon fertig. Den brauchst du nur noch einfügen.
    Der Kommentar war ist wohl nur zur Vollständigkeit da.

    T ist normalerweise die Bezeichnung von generischen Typen. Das heißt, der Typ kann alles sein.
    Da musst Du Dir den entsprechenden Implements IComparer(Of t) implementieren.
    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!
    Guten Tag!
    Ich hatte diesen Thread wohl etwas voreilig als erledigt erklärt.
    Der letzte Hinweis war:
    "Da musst Du Dir den entsprechenden Implements IComparer(Of t) implementieren. "
    Das habe ich versucht, aber es kommt immer der Hinweis, dass der Typ t nicht in den Typ Date umgewandelt werden kann. Hier mein Code

    VB.NET-Quellcode

    1. Sub MeinSortierer(Of t)(ByVal x As List(Of t))
    2. x.Sort(New Sortiercomparer(Of t))
    3. End Sub
    4. Class Sortiercomparer(Of t)
    5. Implements IComparer(Of t)
    6. Dim r As New Random
    7. Public Function Compare(ByVal x As t, ByVal y As t) As Integer Implements System.Collections.Generic.IComparer(Of t).Compare
    8. 'Hier werden normalerweise X und Y miteinander verglichen.
    9. ' Return r.Next(-1, 2)
    10. Try
    11. Dim d1 As Date = CDate(x)
    12. Dim d2 As Date = CDate(y)
    13. Dim rt As Integer = Date.Compare(d1, d2)
    14. Return CInt(IIf(rt < 0, True, False)) ' sortiert nach steigendem Datum
    15. ' Return CInt(IIf(rt > 0, True, False)) ' sortiert nach fallendem Datum
    16. Catch ex As Exception
    17. Return String.Compare(CStr(x), CStr(y)) 'wenn es kein Date ist, nach String sortieren..
    18. End Try
    19. End Function
    20. End Class


    Auch mit dem Versuch, den Datentyp t insgesamt durch Typ Date zu ersetzen schlug ich fehl.
    Wer kann mir weiterhelfen?
    Vielen Dank°!
    el
    ah - sry.

    Jo, für das aufwärts-sortieren kannste einfach

    VB.NET-Quellcode

    1. System.Collections.Generic.Comparer(Of T).Default
    nehmen.
    Was immer sich vergleichen lässt, lässt sich mit diesem Ding auch sortieren :)

    Für Abwärts-Sortierung fund ich jetzt keine allgemeine Lösung, aber man kann sich ja leicht eine schreiben:

    VB.NET-Quellcode

    1. Class DescComparer(Of t) : Implements IComparer(Of t)
    2. Public ReadOnly Default as new DescComparer(Of t)
    3. Public Function Compare(ByVal x As t, ByVal y As t) As Integer Implements System.Collections.Generic.IComparer(Of t).Compare
    4. 'Argumente umgedreht durchreichen
    5. Return System.Collections.Generic.Comparer(Of t).Default.Compare(y, x)
    6. End Function
    7. End Class
    Besten Dank an alle!
    Ich bin schon eifrig am ausprobieren.

    @ ErfinderDes Rades:
    Bei der Zeile: Public Read Only Default as new DescComparer(Of t) wird das "as" als Fehler markiert. Anscheinend funktioniert der Code aber auch ohne diese Zeile richtig. Sollte ich hier noch von mir aus etwas verändern? Event. statt Default einen eigenen Namen einfügen?

    Viele Grüße und nochmals danke!!
    el