Dictionary, doppelte Value in Zufall vermeiden

  • VB.NET

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

    Dictionary, doppelte Value in Zufall vermeiden

    Hallo
    hab nach langer Zeit wieder versucht etwas zu Programmieren. (einen Zeichenketten Generator)
    Hab es mit Dictionary versucht, wobei ich sagen muß das es das erste mal ist das ich Dictionary anwende.
    Hab auf "Google" und "YouTube" Beiträge zu diesem Thema gesucht und dadurch ist mein Programm entstanden.

    Der unten benutzte Code funktioniert, soweit ich das beurteilen kann, ganz gut, bis auf die doppelten Ziehungen.
    Mit dieser Zeile

    Quellcode

    1. dic.Remove(i, dic.Item(i))
    , hab ich versucht mein Problem zu lösen,aber es funktioniert nicht
    Bitte um Hilfe dafür.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Sub btnGenerator_Click(sender As Object, e As EventArgs) Handles btnGenerator.Click
    2. txtZeichenkette.Clear()
    3. Dim z As Integer ' Zufallszahl
    4. Dim i As Integer ' Zähler für anzahl Keys
    5. Dim k As Integer ' Zähler für Zeichenkettelänge
    6. Dim lan As Integer 'Zeichenkettelänge
    7. Dim r As New System.Random ' Zufallsbereich (von bis)
    8. Dim dic As New Dictionary(Of Integer, String())
    9. Dim ak As Integer
    10. ak = 0 'Key
    11. If chkGrossBuchstaben.Checked = True Or chkKleinBuchstaben.Checked = True Or chkSonderzeichen.Checked = True Or chkZahlen.Checked = True Then ' wenn Checkbox.Checked = True
    12. If chkGrossBuchstaben.Checked Then
    13. ak += 1 'erhöht Key um 1
    14. dic.Add(ak, New String() {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
    15. "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"})
    16. End If
    17. If chkKleinBuchstaben.Checked Then
    18. ak += 1 'erhöht Key um 1
    19. dic.Add(ak, New String() {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
    20. "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"})
    21. End If
    22. If chkZahlen.Checked Then
    23. ak += 1 'erhöht Key um 1
    24. dic.Add(ak, New String() {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"})
    25. End If
    26. If chkSonderzeichen.Checked Then
    27. ak += 1 'erhöht Key um 1
    28. dic.Add(ak, New String() {"<", ",", ".", "-", "#", "+", ">", ";", ":", "-", "*", "!", "§", "$", "%",
    29. "&", "(", ")", "=", "?", "ß"})
    30. End If
    31. Else
    32. If chkGrossBuchstaben.Checked = False And chkKleinBuchstaben.Checked = False And chkSonderzeichen.Checked = False And chkZahlen.Checked = False Then
    33. MessageBox.Show("Bitte Zeichen auswählen")
    34. Exit Sub
    35. End If
    36. End If
    37. For k = 1 To Convert.ToInt32(ncZeichenlaenge.Value) ' gewählte Zeichenkettelänge
    38. Do
    39. For i = 1 To dic.Keys.Count ' zählt Anzahl der Keys
    40. z = r.Next(0, dic.Item(i).Length) ' zieht eine Zufallszahl
    41. Dim value() As String = dic.Item(i) ' gezogene Zeichen
    42. txtZeichenkette.Text += value(z) ' ausgabe zufalls Zeichenkette
    43. 'dic.Remove(i, dic.Item(i))
    44. lan += 1 ' Zeichenkettelänge um 1 erhöhen
    45. If lan = Convert.ToInt32(ncZeichenlaenge.Value) Then ' wenn Zeichenkettelänge ist gleich Zähler Zeichenkettelänge
    46. txtMehrereZeichenketten.Text += txtZeichenkette.Text & Environment.NewLine ' Zeichenkette in Textbox ausgeben
    47. Exit Sub
    48. End If
    49. Next i
    50. Loop
    51. Next k
    52. End Sub

    Ich bedanke mich schon mal ,und Hoffe auf Hilfe.
    MfG. Willi
    @papawt Was soll passieren?
    Was passiert statt dessen?
    Was müssen wir tun, um Deinen Effekt zu reproduzieren?
    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!
    hallo
    @papawt Was soll passieren?

    Was passiert statt dessen?

    Was müssen wir tun, um Deinen Effekt zu reproduzieren?


    Versteh nicht die rückfrage .
    Das Problem ist das doppelte Zeichen gezogen werden, und das möchte ich nicht
    und das Pbroblem kann ich nicht beheben.
    MfG. Willi
    Du brauchts 100 Zahlen und es dürfen keine doppelten Zahlen vorhanden sein?
    Man nehme eine Zahlenreihe von 0 - 99 oder von 1 - 100, und mische die mit FisherYales, und schon hast du genau das was du brauchst.

    Es muss einfach eine Zahlenreihe sein, bei der keine doppelten Werte vorhanden sind, egal welche Werte drin sind.

    Freundliche Grüsse

    exc-jdbi
    Mir scheint das Vorgehen auch bisserl umständlich - aber die Anforderungen sind ja nicht klar definiert, und somit unklar, ob andere Vorgehensweisen anwendbar wären.
    FisherYales ist sicher das angesagte Instrument für sowas.
    Aber nur so einfach hingeworfen bringt das evtl nicht so viel - es muss ja richtig eingesetzt werden.
    Der Code sieht ja danach aus, als soll ein Wort gebildet werden unater Hinzuziehung mehrerer Zeichensätze - FisherYales käme also mehrfach zum Zug, und am Besten am Ende fürs Gesamtergebnis noch einmal.

    Wiedemauchsei, hier ein Code, mit dem du aus einem STring mehrfach vorkommende Zeichen entfernst:

    VB.NET-Quellcode

    1. Dim s = "19583zrhd0wdksß=j/hg35"
    2. s = New String(s.Distinct().ToArray)




    Achguck - ich hab hier sogar eine FY-Implementierung:

    VB.NET-Quellcode

    1. Public Module CollectionX
    2. Private _Rnd As New Random
    3. ''' <summary> Fisher-Yates-Mixing up the itms. On seed<0 the random seed is used </summary>
    4. <Extension(), DebuggerStepThrough()>
    5. Public Sub Shuffle(itms As IList, Optional seed As Integer = -1)
    6. If seed >= 0 Then _Rnd = New Random(seed)
    7. For i = itms.Count - 1 To 1 Step -1
    8. itms.Swap(i, _Rnd.Next(i + 1))
    9. Next
    10. End Sub
    11. <Extension(), DebuggerStepThrough()>
    12. Public Sub Swap(items As IList, I1 As Integer, I2 As Integer)
    13. Dim Tmp = items(I1)
    14. items(I1) = items(I2)
    15. items(I2) = Tmp
    16. End Sub
    17. '...
    Aber wie gesagt: Du müsstest deinen Ansatz neu denken - bzw. überhaupt erstmal die Anforderung wasserdicht definieren.
    Vermutlich haben Dictionaries darin nichts verloren - vermute ich.

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

    papawt schrieb:

    wie soll ich das in meinem Code anwenden.
    Algorithmus verstehen.
    Algorithmus implementieren.
    Sehen, was da rauskommt (ein Array mit Zahlen in zufälliger Reihenfolge),
    Werte aus diesem Array entnehmen und anwenden.
    Feddich.
    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!
    Hallo
    @'ErfinderDesRades
    Zitat:"Mir scheint das Vorgehen auch bisserl umständlich - aber die Anforderungen sind ja nicht klar definiert, und somit unklar, ob andere Vorgehensweisen anwendbar wären."
    Ich versuch noch einmal die Anforderungen zu deffinieren.
    [vbnet z = r.Next(0, dic.Item(i).Length) ' zieht eine Zufallszahl
    Dim value() As String = dic.Item(i) ' gezogene Zeichen
    txtZeichenkette.Text += value(z) ' ausgabe zufalls Zeichenkette
    'dic.Remove(i, dic.Item(i))][/vbnet]
    Also ich zieh ein Zufalls Zeichen aus Dictionary
    nachdem das Zeichen gezogen ist soll es aus dem Dictionary entfernt werden,was ich mit

    VB.NET-Quellcode

    1. dic.Remove(i, dic.Item(i))

    versucht habe,aber es fuktioniert nicht.
    Das ist mein Problem.
    MfG. Willi
    Führe Deinen Algo mal ohne Rechner nur mit Papier und Stift "trocken" aus.
    Mach das mit 3 Zahlen und schreib auf, welche Elemente sich wo befinden, was Du wo rausnimmst und was danach noch drinne ist.
    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!

    papawt schrieb:


    Ich versuch noch einmal die Anforderungen zu deffinieren.
    [vbnet z = r.Next(0, dic.Item(i).Length) ' zieht eine Zufallszahl
    Dim value() As String = dic.Item(i) ' gezogene Zeichen
    txtZeichenkette.Text += value(z) ' ausgabe zufalls Zeichenkette
    'dic.Remove(i, dic.Item(i))][/vbnet]
    Also ich zieh ein Zufalls Zeichen aus Dictionary
    nachdem das Zeichen gezogen ist soll es aus dem Dictionary entfernt werden,was ich mit

    VB.NET-Quellcode

    1. dic.Remove(i, dic.Item(i))

    versucht habe,aber es fuktioniert nicht.
    Das ist mein Problem.
    MfG. Willi
    Ich kann den Code nicht lesen, bzw. nur ganz von ungefähr.
    Scheinbar versuchst du etwas aus dem Dic zu entfernen, was in dieser Form garnet darinnen ist.
    Aber bitte stelle Codes leserlich ein, dann kann ich auch darauf eingehen.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. For k = 1 To Convert.ToInt32(ncZeichenlaenge.Value) ' gewählte Zeichenkettelänge
    2. Do
    3. For i = 1 To dic.Keys.Count ' zählt Anzahl der Keys
    4. z = r.Next(0, dic.Item(i).Length) ' zieht eine Zufallszahl
    5. Dim value() As String = dic.Item(i) ' gezogene Zeichen
    6. txtZeichenkette.Text += value(z) ' ausgabe zufalls Zeichenkette
    7. 'dic.Remove(i, dic.Item(i))
    8. lan += 1 ' Zeichenkettelänge um 1 erhöhen
    9. If lan = Convert.ToInt32(ncZeichenlaenge.Value) Then ' wenn Zeichenkettelänge ist gleich Zähler Zeichenkettelänge
    10. txtMehrereZeichenketten.Text += txtZeichenkette.Text & Environment.NewLine ' Zeichenkette in Textbox ausgeben
    11. Exit Sub
    12. End If
    13. Next i
    14. Loop
    15. Next k

    papawt schrieb:

    nachdem das Zeichen gezogen ist soll es aus dem Dictionary entfernt werden
    Jo - aber in dem Dictionary sind ja gar keine Zeichen drinne.
    Da sind ja ganze Zeichensätze drinne.
    Du wirst ja sicherlich nicht den ganzen Zeichensatz weghauen wollen, nachdem ein einziges Zeichen daraus verwendet wurde.
    Nein - in zweierlei Hinsicht:
    1. Es sind Strings, also Zeichenketten
      Zufälligerweise sind deine Strings alle genau von Länge 1, also enthalten genau ein Zeichen - da kann man es hingehen lassen, sie im weiteren Sinne als "Zeichen" zu bezeichnen.
      Aber Verwirrung ist damit schoma programmiert, denn für Zeichen im engeren Sinne gibt es einen eigenen Datentyp: Char
    2. New String() {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
      ist kein String , sondern ein String-Array.
      String und String-Array ist natürlich ein Riesen-Unterschied.
      Ein Autohaus ist ja auch kein Auto

    Hallo
    so wie du das sagst, seh ich das jetzt auch ein.
    Aber wie kann ich jetzt mein Problem lösen.
    also wenn ich ein "A",")",oder was anderes aus dem Dictionary in die Textbox ein gefügt habe,
    das eben dieses "Zeichen" nicht nochmal gezogen wird.
    Das, hab ich so Gedacht, geht mit

    VB.NET-Quellcode

    1. dic.Remove(i, dic.Item(i))
    .
    aber das ist ja nicht so.Wie macht man es also Richtig?
    MfG. Willi
    Dictionary ist für dein Vorhaben extrem unhandlich.
    Aber versteh erstmal, dass jeder deiner Dic-Einträge einen Zeichensatz darstellen sollte.
    Der Zeichensätze sind bei dir viere angelegt, nämlich:

    VB.NET-Quellcode

    1. New String() {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
    2. New String() {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
    3. New String() {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}
    4. New String() {"<", ",", ".", "-", "#", "+", ">", ";", ":", "-", "*", "!", "§", "$", "%", "&", "(", ")", "=", "?", "ß"}
    Das kann man viel einfacher haben:

    VB.NET-Quellcode

    1. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    2. "abcdefghijklmnopqrstuvwxyz"
    3. "1234567890"
    4. "<,.-#+>;:-*!§$%&()=?ß"

    Also verwende einfache Strings als Zeichensatz.
    Mit String.Substring() kannst du auch ein Zeichen entnehmen, und mit String.Replace oder String.RemoveAt() eines entfernen.
    viel einfacher.
    Ansonsten ist dein Ansatz zwar umständlich, aber grundsätzlich nicht ganz die falsche Richtung:
    Ein grundgedanke auch von Fisher-Yates ist, benutzte Elemente der betrachteten Menge zu entziehen.

    papawt schrieb:

    Googlen
    Hmm, naja - es geht auch einfacher:
    VisualStudio richtig nutzen (Google ist nicht deine Mami)



    Guck, ich hab jetzt auch mal einen neuen Ansatz für dich gebastelt:

    VB.NET-Quellcode

    1. Public Sub btnGenerator_Click(sender As Object, e As EventArgs) Handles btnGenerator.Click
    2. txtZeichenkette.Clear()
    3. Dim z As Integer ' Zufallszahl
    4. Dim i As Integer ' Zähler für anzahl Keys
    5. Dim k As Integer ' Zähler für Zeichenkettelänge
    6. Dim lan As Integer 'Zeichenkettelänge
    7. Dim r As New System.Random ' Zufallsbereich (von bis)
    8. Dim zeichenSaetze As New List(Of String)
    9. Dim ak As Integer
    10. ak = 0 'Key
    11. If chkGrossBuchstaben.Checked Then zeichenSaetze.Add("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
    12. If chkKleinBuchstaben.Checked Then zeichenSaetze.Add("abcdefghijklmnopqrstuvwxyz")
    13. If chkZahlen.Checked Then zeichenSaetze.Add("1234567890")
    14. If chkSonderzeichen.Checked Then zeichenSaetze.Add("<,.-#+>;:-*!§$%&()=?ß")
    15. If zeichenSaetze.Count = 0 Then
    16. MessageBox.Show("Bitte ZeichenSätze auswählen")
    17. Exit Sub
    18. End If
    19. 'ab hier dein Stiefel weitermachen...
    20. For k = 1 To Convert.ToInt32(ncZeichenlaenge.Value) ' gewählte Zeichenkettelänge
    21. Do
    22. For i = 1 To dic.Keys.Count ' zählt Anzahl der Keys
    23. z = r.Next(0, dic.Item(i).Length) ' zieht eine Zufallszahl
    24. Dim value() As String = dic.Item(i) ' gezogene Zeichen
    25. txtZeichenkette.Text += value(z) ' ausgabe zufalls Zeichenkette
    26. 'dic.Remove(i, dic.Item(i))
    27. lan += 1 ' Zeichenkettelänge um 1 erhöhen
    28. If lan = Convert.ToInt32(ncZeichenlaenge.Value) Then ' wenn Zeichenkettelänge ist gleich Zähler Zeichenkettelänge
    29. txtMehrereZeichenketten.Text += txtZeichenkette.Text & Environment.NewLine ' Zeichenkette in Textbox ausgeben
    30. Exit Sub
    31. End If
    32. Next i
    33. Loop
    34. Next k
    35. End Sub

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

    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!